langgenius/dify · error · NotFoundError

not_found

not_found

Error message

Workflow run not found

What it means

Thrown by GET /apps/{app_id}/workflow-runs/{run_id} when WorkflowRunService.get_workflow_run cannot locate a run with the given run_id for the app. The run may not exist or may belong to a different app. Returned as 404 code 'not_found'.

Source

Thrown at api/controllers/console/app/workflow_run.py:394

        "Workflow run detail retrieved successfully",
        console_ns.models[WorkflowRunDetailResponse.__name__],
    )
    @console_ns.response(404, "Workflow run not found")
    @setup_required
    @login_required
    @account_initialization_required
    @rbac_permission_required(RBACResourceScope.APP, RBACPermission.APP_CREATE_AND_MANAGEMENT)
    @get_app_model(mode=[AppMode.ADVANCED_CHAT, AppMode.WORKFLOW])
    def get(self, app_model: App, run_id: UUID):
        """
        Get workflow run detail
        """
        run_id_str = str(run_id)

        workflow_run_service = WorkflowRunService()
        workflow_run = workflow_run_service.get_workflow_run(app_model=app_model, run_id=run_id_str)
        if workflow_run is None:
            raise NotFoundError("Workflow run not found")

        return WorkflowRunDetailResponse.model_validate(workflow_run, from_attributes=True).model_dump(mode="json")


@console_ns.route("/apps/<uuid:app_id>/workflow-runs/<uuid:run_id>/node-executions")
class WorkflowRunNodeExecutionListApi(Resource):
    @console_ns.doc("get_workflow_run_node_executions")
    @console_ns.doc(description="Get workflow run node execution list")
    @console_ns.doc(params={"app_id": "Application ID", "run_id": "Workflow run ID"})
    @console_ns.response(
        200,
        "Node executions retrieved successfully",
        console_ns.models[WorkflowRunNodeExecutionListResponse.__name__],
    )
    @console_ns.response(404, "Workflow run not found")
    @setup_required
    @login_required
    @account_initialization_required

View on GitHub (pinned to ef8544b173)

Solutions

  1. List runs via GET /apps/{app_id}/workflow-runs to obtain a valid run_id before fetching detail.
  2. Confirm run_id belongs to app_id; cross-app references return None.
  3. If the run was just published, retry after the run record is committed (brief propagation window).
  4. Check the workflow_runs table for the run_id to rule out deletion.
Defensive patterns

Strategy: try-catch

Validate before calling

const runs = await get(`/apps/${appId}/workflow-runs`);
const exists = runs.data.some(r => r.id === runId);
if (!exists) { /* do not fetch detail */ }

Try / catch

try {
  await get(`/apps/${appId}/workflow-runs/${runId}`);
} catch (e) {
  if (e.code === 'not_found' && /workflow run not found/i.test(e.message)) {
    // show 'run expired or unknown' state, refresh runs list
  } else { throw e; }
}

Prevention

When it happens

Trigger: GET /console/api/apps/{app_id}/workflow-runs/{run_id} where run_id is unknown, was deleted, belongs to another app, or is malformed (but passed URL UUID parsing).

Common situations: User clicks a stale run link from history/email after the run was purged; copying a run_id across environments; race condition where the run is still being committed; passing the app run id instead of the workflow run id.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/cfa1b82c73fbca80. Report an issue: GitHub.