A failed deployment is silent: workflow returns to NONE with deployment_error null

Symptom

A workflow whose deployment fails returns to not deployed with deployment_error: null. The reason exists only in the Worker logs, which a user without cluster access cannot read. Nothing in the UI or the API says what went wrong — or that anything went wrong at all.

Reported against 26.9.0.

Root cause — confirmed in the code

studio/ryax/studio/application/workflow_service.py:368-377:

def undeploy_workflow_success(self, workflow_id: str, error: Optional[str] = None) -> None:
    with self.uow:
        workflow = self.uow.workflows.get_workflow(workflow_id)
        if not error:
            workflow.undeploy_success()          # status -> NONE
        else:
            workflow.undeploy_with_error(error)  # status -> ERROR, message kept
        self.uow.commit()

error is optional and defaults to None, so any failure that arrives without a message string takes the success branch and is indistinguishable from a deliberate undeploy.

deployment_error is cleared at the start of every deploy (studio/ryax/studio/domain/workflow/entities/workflow.py:653), and undeploy_success() (:776) sets deployment_status = NONE without touching it. So the field is reliably null on this path — there is no stale value to notice either.

The plumbing to report this is entirely in place and unused: the column (infrastructure/database/metadata.py:159), the API field (infrastructure/api/models/workflow.py:49) and the view (domain/workflow/views/workflow_view.py:33) all exist.

Reproduction

Any deployment failure that does not carry an error string — the demo hit it via the addon/definition failure filed separately, where the Worker kills the pod a few seconds after start.

Observed: GET /api/studio/workflows/<id> returns deployment_status: "NONE", deployment_error: null, and the only account of the failure is in the Worker pod logs.

Why it matters

It converts every deployment failure into a silent no-op for anyone without kubectl. It also makes the failures filed alongside this one far harder to diagnose than they need to be — the demo only found them by reading Worker logs.

Acceptance criteria

  • A failed deployment leaves the workflow in ERROR with a non-null deployment_error, or it is documented why a given failure cannot carry one.
  • Callers of undeploy_workflow_success are audited: which of them mean "undeployed on purpose" and which mean "failed"? The shared name and the optional argument are what allow the two to be confused.

Workaround in place

The demo checks status and URL after every deployment rather than trusting the reported state.


Found while migrating the CAPE demo to Ryax 26.9.0: ryax-tech/public/cape-tools/cape-agentic-infra#2 (comment 3905714558)