langgenius/dify · info · NotFound
last run not found
Error message
last run not found
What it means
HTTP 404 NotFound('last run not found') raised by DraftWorkflowNodeLastRunApi.get (GET /apps/{app_id}/workflows/draft/nodes/{node_id}/last-run) when WorkflowService.get_node_last_run returns None. The draft workflow exists, but no execution record exists for the given node_id (the node was never run in the debugger).
Source
Thrown at api/controllers/console/app/workflow.py:1675
@console_ns.response(404, "Node last run not found")
@console_ns.response(403, "Permission denied")
@setup_required
@login_required
@account_initialization_required
@rbac_permission_required(RBACResourceScope.APP, RBACPermission.APP_VIEW_LAYOUT)
@get_app_model(mode=[AppMode.ADVANCED_CHAT, AppMode.WORKFLOW])
def get(self, app_model: App, node_id: str):
srv = WorkflowService()
workflow = srv.get_draft_workflow(app_model, session=db.session())
if not workflow:
raise NotFound("Workflow not found")
node_exec = srv.get_node_last_run(
app_model=app_model,
workflow=workflow,
node_id=node_id,
)
if node_exec is None:
raise NotFound("last run not found")
return WorkflowRunNodeExecutionResponse.model_validate(node_exec, from_attributes=True).model_dump(mode="json")
@console_ns.route("/apps/<uuid:app_id>/workflows/draft/trigger/run")
class DraftWorkflowTriggerRunApi(Resource):
"""
Full workflow debug - Polling API for trigger events
Path: /apps/<uuid:app_id>/workflows/draft/trigger/run
"""
@console_ns.doc("poll_draft_workflow_trigger_run")
@console_ns.doc(description="Poll for trigger events and execute full workflow when event arrives")
@console_ns.doc(params={"app_id": "Application ID"})
@console_ns.expect(
console_ns.model(
"DraftWorkflowTriggerRunRequest",
{
"node_id": fields.String(required=True, description="Node ID"),View on GitHub (pinned to ef8544b173)
Solutions
- Run the node once (POST .../nodes/{node_id}/run) before fetching its last-run.
- Verify the node_id matches a node present in the draft graph.
- Treat this 404 as a non-error 'no data yet' state in the UI.
Defensive patterns
Strategy: try-catch
Validate before calling
// Run the node at least once before fetching its last-run. const lastRun = await safeGetLastRun(appId, nodeId); if (!lastRun) await runDraftNode(appId, nodeId);
Type guard
const hasLastRun = (r): r is {id: string} => !!r && typeof r.id === 'string'; Try / catch
try {
return await getNodeLastRun(appId, nodeId);
} catch (e) {
if (e?.status === 404 && /last run not found/i.test(e?.message)) {
return null; // no data yet — treat as empty state
}
throw e;
} Prevention
- Treat 'last run not found' as an empty state, not a hard error.
- Verify node_id exists in the draft graph before polling.
- Run the node once before enabling the last-run panel.
When it happens
Trigger: Polling/reading the last-run result for a node that has never been executed, or whose prior execution record is gone.
Common situations: User opens the node inspector before running the node; node_id is wrong/renamed; execution history was cleared.
Related errors
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/04378bab676a66be.
Report an issue: GitHub.