Payload and error
All data types passed between nodes, I .e. workflow payload, must inherit WorkflowPayload. The type comes from the core package:
export interface WorkflowPayload {
errCode: number;
errMessage: string;
}
Successful output unified use:
{
errCode: 0,
errMessage: ""
}
Output payload
Output node should explicitly return objects containing errCode, errMessage, and items:
interface WorkflowOutputItem {
id: string;
title: string;
content: unknown;
contentType?: "markdown" | "text" | "json" | "audio";
collapsed?: boolean;
}
interface OutputPayload extends WorkflowPayload {
items: WorkflowOutputItem[];
}
const outputNode = workflow.createOutputNode<Parsed, OutputPayload>({
name: "output",
format(result) {
return workflow.createOutputPayload({
items: [{
title: "Result",
content: result,
contentType: "json",
collapsed: false,
}],
});
},
});
items is currently the only user-visible output carrier. This array is read by Desktop, server embed, server/web log, and external response; the full output of assistant messages is also stored in items instead of the top-level content. In a Conversation project, the default markdown/text assistant answer titled Output is rendered directly in the transcript even when it carries a finish reason, token usage, or Provider metadata. Details blocks remain reserved for tool calls, reasoning, diagnostics, structured supporting results, and explicitly customized or collapsed output.
If the business fails but executor does not crash, you can return a non-zero errCode and a readable errMessage. The external Dify style API reads the errCode in the final report: only executor succeeds and errCode === 0 is mapped to succeeded.
WorkflowResult
The underlying safe run will first normalize the execution result of workflow:
type WorkflowResult<T> =
| { ok: true; data: T }
| { ok: false; error: SerializedWorkflowError };
When generating an execution report,runtime converts the failure result of ok: false into a readable payload:
{
ok: true,
data: {
errCode,
errMessage,
output: null
}
}
This way Desktop, server web, CLI JSON, and external API can all read result.data.errCode together. A normal success result will synthesize the final return value and the node output named output into result.data.output; if either payload has a non-zero errCode, the report retains the business error code.
User Input Waiting
The user input node will pause workflow into the persistent waiting_for_input state instead of marking it as a normal failure. The report will contain:
| Field | Description |
|---|---|
pendingUserInput | The currently waiting request, including requestId, node name, title, description, form params, default value, and node metadata. |
resolvedUserInputs | An array of submitted answers for this run, containing requestId, node names, values, and submittedAt. |
Runtime event emits user_input_requested and user_input_resolved. The standard error code mapping for the wait state is 202, which is used to indicate that workflow is still recoverable; the node payload after a successful recovery must still inherit WorkflowPayload, which contains errCode: 0, errMessage: "", requestId, values, and submittedAt by default.
WorkflowError
Can proactively throw workflow.WorkflowError, with type, message, node and metadata. The framework also converts ordinary exceptions to WorkflowError.
Common error types include:
- Input validation failed.
- Node execution failed.
- workflow execution failed.
- User input waits.
- Tool permission denied.
- File parsing failed.
- provider call failed.
- abort or timeout.
Errors are serialized to avoid directly exposing the full stack or the original response of a third-party SDK.
Errors in the UI
- A local Desktop run writes stdout, stderr, and the report to the local run cache.
- server run will persist
RunResult, and log pages are read from/api/workflows/{name}/runs/{runId}. waiting_for_inputrun will keeppendingUserInput, and Desktop/server embed can submit the answer to restore the samerunId.- The external blocking API returns
data.error;streaming API fails through SSEerroror finalworkflow_finishedexpression.