workflow 5.0.0-beta.5 → 5.0.0-beta.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -23
- package/dist/api-workflow.d.ts +1 -1
- package/dist/api-workflow.d.ts.map +1 -1
- package/dist/api-workflow.js +1 -1
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +5 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/internal/builtins.d.ts +20 -3
- package/dist/internal/builtins.d.ts.map +1 -1
- package/dist/internal/builtins.js +68 -4
- package/dist/internal/errors.d.ts +1 -1
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +2 -2
- package/dist/nest-builder.d.ts +2 -0
- package/dist/nest-builder.d.ts.map +1 -0
- package/dist/nest-builder.js +2 -0
- package/dist/nest-vercel-builder.d.ts +2 -0
- package/dist/nest-vercel-builder.d.ts.map +1 -0
- package/dist/nest-vercel-builder.js +2 -0
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/runtime.d.ts +2 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +4 -1
- package/docs/ai/chat-session-modeling.mdx +29 -26
- package/docs/ai/defining-tools.mdx +6 -7
- package/docs/ai/human-in-the-loop.mdx +11 -11
- package/docs/ai/index.mdx +50 -45
- package/docs/ai/message-queueing.mdx +16 -16
- package/docs/ai/meta.json +1 -0
- package/docs/ai/resumable-streams.mdx +40 -28
- package/docs/ai/sleep-and-delays.mdx +10 -10
- package/docs/ai/streaming-updates-from-tools.mdx +6 -6
- package/docs/api-reference/index.mdx +24 -0
- package/docs/api-reference/meta.json +8 -0
- package/docs/api-reference/vitest/index.mdx +9 -15
- package/docs/api-reference/workflow/create-hook.mdx +89 -10
- package/docs/api-reference/workflow/create-webhook.mdx +16 -15
- package/docs/api-reference/workflow/define-hook.mdx +35 -33
- package/docs/api-reference/workflow/fatal-error.mdx +30 -8
- package/docs/api-reference/workflow/fetch.mdx +14 -10
- package/docs/api-reference/workflow/get-step-metadata.mdx +2 -2
- package/docs/api-reference/workflow/get-workflow-metadata.mdx +3 -3
- package/docs/api-reference/workflow/get-writable.mdx +7 -7
- package/docs/api-reference/workflow/index.mdx +4 -1
- package/docs/api-reference/workflow/retryable-error.mdx +1 -1
- package/docs/api-reference/workflow/set-attributes.mdx +61 -0
- package/docs/api-reference/workflow/sleep.mdx +4 -4
- package/docs/api-reference/workflow-ai/durable-agent.mdx +48 -86
- package/docs/api-reference/workflow-ai/index.mdx +3 -3
- package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +67 -24
- package/docs/api-reference/workflow-api/get-hook-by-token.mdx +26 -12
- package/docs/api-reference/workflow-api/get-run.mdx +43 -8
- package/docs/api-reference/workflow-api/index.mdx +6 -10
- package/docs/api-reference/workflow-api/resume-hook.mdx +73 -12
- package/docs/api-reference/workflow-api/resume-webhook.mdx +11 -9
- package/docs/api-reference/workflow-api/start.mdx +60 -13
- package/docs/api-reference/workflow-astro/index.mdx +18 -0
- package/docs/api-reference/workflow-astro/meta.json +4 -0
- package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
- package/docs/api-reference/workflow-errors/entity-conflict-error.mdx +4 -4
- package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
- package/docs/api-reference/workflow-errors/hook-not-found-error.mdx +8 -8
- package/docs/api-reference/workflow-errors/index.mdx +88 -0
- package/docs/api-reference/workflow-errors/meta.json +6 -0
- package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +68 -0
- package/docs/api-reference/workflow-errors/run-expired-error.mdx +2 -2
- package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/step-not-registered-error.mdx +5 -5
- package/docs/api-reference/workflow-errors/throttle-error.mdx +2 -2
- package/docs/api-reference/workflow-errors/too-early-error.mdx +2 -2
- package/docs/api-reference/workflow-errors/workflow-error.mdx +52 -0
- package/docs/api-reference/workflow-errors/workflow-not-registered-error.mdx +5 -6
- package/docs/api-reference/workflow-errors/workflow-run-cancelled-error.mdx +6 -6
- package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +5 -5
- package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/workflow-run-not-found-error.mdx +4 -4
- package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/workflow-world-error.mdx +8 -8
- package/docs/api-reference/workflow-globals.mdx +14 -10
- package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -0
- package/docs/api-reference/workflow-nest/index.mdx +31 -0
- package/docs/api-reference/workflow-nest/meta.json +9 -0
- package/docs/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
- package/docs/api-reference/workflow-nest/workflow-controller.mdx +40 -0
- package/docs/api-reference/workflow-nest/workflow-module.mdx +74 -0
- package/docs/api-reference/workflow-next/with-workflow.mdx +39 -17
- package/docs/api-reference/workflow-nitro/index.mdx +60 -0
- package/docs/api-reference/workflow-nuxt/index.mdx +48 -0
- package/docs/api-reference/workflow-observability/hydrate-data.mdx +35 -0
- package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
- package/docs/api-reference/workflow-observability/index.mdx +62 -0
- package/docs/api-reference/workflow-observability/meta.json +11 -0
- package/docs/api-reference/workflow-observability/observability-revivers.mdx +50 -0
- package/docs/api-reference/workflow-observability/parse-class-name.mdx +41 -0
- package/docs/api-reference/workflow-observability/parse-step-name.mdx +40 -0
- package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
- package/docs/api-reference/workflow-runtime/create-world.mdx +39 -0
- package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/get-world.mdx +11 -14
- package/docs/api-reference/workflow-runtime/health-check.mdx +50 -0
- package/docs/api-reference/workflow-runtime/index.mdx +41 -0
- package/docs/api-reference/workflow-runtime/meta.json +12 -0
- package/docs/api-reference/workflow-runtime/set-world.mdx +51 -0
- package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +43 -0
- package/docs/api-reference/workflow-runtime/world/analytics.mdx +315 -0
- package/docs/api-reference/workflow-runtime/world/index.mdx +60 -0
- package/docs/api-reference/workflow-runtime/world/meta.json +4 -0
- package/docs/api-reference/workflow-runtime/world/queue.mdx +88 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/storage.mdx +98 -34
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/streams.mdx +8 -8
- package/docs/api-reference/workflow-serde/index.mdx +1 -2
- package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +3 -4
- package/docs/api-reference/workflow-serde/workflow-serialize.mdx +8 -8
- package/docs/api-reference/workflow-sveltekit/index.mdx +18 -0
- package/docs/api-reference/workflow-sveltekit/meta.json +4 -0
- package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
- package/docs/api-reference/workflow-vite/index.mdx +18 -0
- package/docs/api-reference/workflow-vite/meta.json +4 -0
- package/docs/api-reference/workflow-vite/workflow.mdx +48 -0
- package/docs/changelog/attributes-mvp.mdx +380 -0
- package/docs/changelog/batched-event-writes.mdx +79 -0
- package/docs/changelog/eager-processing.mdx +110 -436
- package/docs/changelog/index.mdx +4 -2
- package/docs/changelog/lazy-event-creation.md +127 -0
- package/docs/changelog/lazy-hook-resume.mdx +78 -0
- package/docs/changelog/meta.json +11 -1
- package/docs/changelog/resilient-resume.mdx +32 -0
- package/docs/changelog/resilient-start.mdx +33 -285
- package/docs/changelog/step-message-ownership.mdx +360 -0
- package/docs/changelog/turbo-mode.md +87 -0
- package/docs/comparisons/index.mdx +66 -0
- package/docs/comparisons/meta.json +11 -0
- package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
- package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
- package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
- package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
- package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
- package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +104 -0
- package/docs/configuration/build-and-diagnostics.mdx +70 -0
- package/docs/configuration/cli-and-web-ui.mdx +241 -0
- package/docs/configuration/framework-options.mdx +165 -0
- package/docs/configuration/index.mdx +32 -0
- package/docs/configuration/meta.json +12 -0
- package/docs/configuration/runtime-tuning.mdx +376 -0
- package/docs/configuration/worlds.mdx +313 -0
- package/docs/cookbook/advanced/child-workflows.mdx +211 -264
- package/docs/cookbook/advanced/meta.json +6 -1
- package/docs/cookbook/advanced/publishing-libraries.mdx +65 -56
- package/docs/cookbook/advanced/serializable-steps.mdx +28 -20
- package/docs/cookbook/advanced/upgrading-workflows.mdx +199 -0
- package/docs/cookbook/agent-patterns/agent-cancellation.mdx +27 -19
- package/docs/cookbook/agent-patterns/durable-agent.mdx +14 -142
- package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +30 -22
- package/docs/cookbook/common-patterns/batching.mdx +18 -14
- package/docs/cookbook/common-patterns/idempotency.mdx +41 -53
- package/docs/cookbook/common-patterns/rate-limiting.mdx +8 -4
- package/docs/cookbook/common-patterns/saga.mdx +23 -19
- package/docs/cookbook/common-patterns/scheduling.mdx +34 -22
- package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +29 -25
- package/docs/cookbook/common-patterns/timeouts.mdx +26 -21
- package/docs/cookbook/common-patterns/webhooks.mdx +10 -6
- package/docs/cookbook/common-patterns/workflow-composition.mdx +30 -27
- package/docs/cookbook/index.mdx +22 -21
- package/docs/cookbook/integrations/ai-sdk.mdx +85 -47
- package/docs/cookbook/integrations/chat-sdk.mdx +50 -33
- package/docs/cookbook/integrations/sandbox.mdx +62 -45
- package/docs/deploying.mdx +95 -0
- package/docs/errors/abort-signal-timeout-in-workflow.mdx +16 -12
- package/docs/errors/corrupted-event-log.mdx +29 -18
- package/docs/errors/deployment-mismatch.mdx +71 -0
- package/docs/errors/fetch-in-workflow.mdx +11 -7
- package/docs/errors/hook-conflict.mdx +69 -13
- package/docs/errors/index.mdx +2 -36
- package/docs/errors/node-js-module-in-workflow.mdx +9 -5
- package/docs/errors/replay-divergence.mdx +27 -0
- package/docs/errors/run-expired.mdx +85 -0
- package/docs/errors/runtime-decryption-failed.mdx +77 -0
- package/docs/errors/serialization-failed.mdx +44 -12
- package/docs/errors/start-invalid-workflow-function.mdx +9 -5
- package/docs/errors/step-executed-multiple-times.mdx +23 -0
- package/docs/errors/step-not-registered.mdx +6 -6
- package/docs/errors/timeout-in-workflow.mdx +12 -8
- package/docs/errors/webhook-invalid-respond-with-value.mdx +18 -18
- package/docs/errors/webhook-response-not-sent.mdx +20 -16
- package/docs/errors/workflow-not-registered.mdx +5 -5
- package/docs/foundations/cancellation.mdx +31 -32
- package/docs/foundations/errors-and-retries.mdx +42 -11
- package/docs/foundations/hooks.mdx +64 -35
- package/docs/foundations/idempotency.mdx +244 -12
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +2 -1
- package/docs/foundations/serialization.mdx +21 -22
- package/docs/foundations/starting-workflows.mdx +106 -30
- package/docs/foundations/streaming.mdx +107 -59
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/foundations/workflows-and-steps.mdx +9 -9
- package/docs/getting-started/astro.mdx +22 -18
- package/docs/getting-started/express.mdx +15 -11
- package/docs/getting-started/fastify.mdx +15 -11
- package/docs/getting-started/hono.mdx +15 -11
- package/docs/getting-started/index.mdx +10 -3
- package/docs/getting-started/meta.json +3 -1
- package/docs/getting-started/nestjs.mdx +87 -20
- package/docs/getting-started/next.mdx +22 -16
- package/docs/getting-started/nitro.mdx +22 -18
- package/docs/getting-started/nuxt.mdx +15 -11
- package/docs/getting-started/python.mdx +135 -40
- package/docs/getting-started/react-router/index.mdx +33 -0
- package/docs/getting-started/react-router/meta.json +5 -0
- package/docs/getting-started/react-router/v7.mdx +237 -0
- package/docs/getting-started/react-router/v8.mdx +232 -0
- package/docs/getting-started/sveltekit.mdx +20 -16
- package/docs/getting-started/tanstack-start.mdx +17 -13
- package/docs/getting-started/vite.mdx +15 -11
- package/docs/how-it-works/cancellation.mdx +63 -63
- package/docs/how-it-works/code-transform.mdx +83 -67
- package/docs/how-it-works/encryption.mdx +30 -26
- package/docs/how-it-works/event-sourcing.mdx +98 -34
- package/docs/how-it-works/framework-integrations.mdx +96 -337
- package/docs/how-it-works/understanding-directives.mdx +22 -22
- package/docs/internal/index.mdx +6 -4
- package/docs/internal/meta.json +6 -1
- package/docs/internal/nitro-native-build.mdx +38 -0
- package/docs/internal/nitro-web-ui.mdx +24 -0
- package/docs/internal/serializable-abort-controller.mdx +7 -7
- package/docs/meta.json +3 -2
- package/docs/observability/attributes.mdx +134 -0
- package/docs/observability/index.mdx +32 -10
- package/docs/observability/meta.json +1 -1
- package/docs/observability/retention.mdx +93 -0
- package/docs/observability/tracing.mdx +124 -0
- package/docs/testing/index.mdx +36 -36
- package/docs/testing/server-based.mdx +10 -10
- package/docs/whats-new.mdx +186 -0
- package/package.json +17 -14
- package/docs/api-reference/workflow-api/world/index.mdx +0 -58
- package/docs/api-reference/workflow-api/world/meta.json +0 -4
- package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
- package/docs/api-reference/workflow-api/world/queue.mdx +0 -86
- package/docs/deploying/building-a-world.mdx +0 -251
- package/docs/deploying/index.mdx +0 -95
- package/docs/deploying/meta.json +0 -4
- package/docs/deploying/world/local-world.mdx +0 -84
- package/docs/deploying/world/meta.json +0 -4
- package/docs/deploying/world/postgres-world.mdx +0 -224
- package/docs/deploying/world/vercel-world.mdx +0 -179
- package/docs/migration-guides/index.mdx +0 -34
- package/docs/migration-guides/meta.json +0 -9
- package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -363
- package/docs/migration-guides/migrating-from-inngest.mdx +0 -314
- package/docs/migration-guides/migrating-from-temporal.mdx +0 -318
- package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -337
|
@@ -10,15 +10,19 @@ related:
|
|
|
10
10
|
- /docs/api-reference/workflow/define-hook
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
<CopyPrompt
|
|
14
|
+
text="Fix hook token conflicts. Find every `createHook({ token })` or typed hook creation site. If multiple waits can exist at the same time, include a unique stable discriminator in the token such as `${workflowRunId}:approval:${itemId}` or `${orderId}:${attempt}` instead of reusing one global token. If duplicate work should join an existing run, catch `HookConflictError` from `@workflow/errors`, read the conflicting run ID from the error/result if available, and use `getRun(runId)` plus `resumeHook()` from `workflow/api` to deliver the payload to the active run. Keep token generation deterministic across retries so replay does not create new hook identities. Verify two concurrent runs and a duplicate request no longer throw hook-conflict unexpectedly."
|
|
15
|
+
/>
|
|
16
|
+
|
|
13
17
|
This error occurs when you try to create a hook with a token that is already in use by another active workflow run. Hook tokens must be unique across all running workflows in your project.
|
|
14
18
|
|
|
15
|
-
## Error
|
|
19
|
+
## Error message
|
|
16
20
|
|
|
17
|
-
```
|
|
21
|
+
```text
|
|
18
22
|
Hook token "<token>" is already in use by another workflow
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
## Why
|
|
25
|
+
## Why this happens
|
|
22
26
|
|
|
23
27
|
Hooks use tokens to identify incoming webhook payloads. When you create a hook with `createHook({ token: "my-token" })`, the Workflow runtime reserves that token for your workflow run. If another workflow run is already using that token, a conflict occurs.
|
|
24
28
|
|
|
@@ -27,9 +31,9 @@ This typically happens when:
|
|
|
27
31
|
1. **Two workflows start simultaneously** with the same hardcoded token
|
|
28
32
|
2. **A previous workflow run is still waiting** for a hook when a new run tries to use the same token
|
|
29
33
|
|
|
30
|
-
## Common
|
|
34
|
+
## Common causes
|
|
31
35
|
|
|
32
|
-
### Hardcoded
|
|
36
|
+
### Hardcoded token values
|
|
33
37
|
|
|
34
38
|
{/* @skip-typecheck: incomplete code sample */}
|
|
35
39
|
```typescript lineNumbers
|
|
@@ -57,7 +61,7 @@ export async function processPayment(orderId: string) {
|
|
|
57
61
|
}
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
### Omitting the
|
|
64
|
+
### Omitting the token (auto-generated)
|
|
61
65
|
|
|
62
66
|
The safest approach is to let the Workflow runtime generate a unique token automatically:
|
|
63
67
|
|
|
@@ -73,9 +77,9 @@ export async function processPayment() {
|
|
|
73
77
|
}
|
|
74
78
|
```
|
|
75
79
|
|
|
76
|
-
## Handling
|
|
80
|
+
## Handling hook conflicts
|
|
77
81
|
|
|
78
|
-
When a hook conflict occurs, awaiting the hook will throw a `HookConflictError`.
|
|
82
|
+
When a hook conflict occurs, awaiting the hook will throw a `HookConflictError`. The error exposes the token that conflicted and, for current worlds, the run ID that currently owns it. `conflictingRunId` remains optional for compatibility with older persisted events and world implementations, so guard it before delegating:
|
|
79
83
|
|
|
80
84
|
```typescript lineNumbers
|
|
81
85
|
import { createHook } from "workflow";
|
|
@@ -93,26 +97,76 @@ export async function processPayment(orderId: string) {
|
|
|
93
97
|
if (HookConflictError.is(error)) { // [!code highlight]
|
|
94
98
|
// Another workflow is already processing this order
|
|
95
99
|
console.log(`Conflicting token: ${error.token}`);
|
|
96
|
-
|
|
100
|
+
if (error.conflictingRunId) {
|
|
101
|
+
console.log(`Active run: ${error.conflictingRunId}`);
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
reason: "duplicate-processing",
|
|
106
|
+
token: error.token,
|
|
107
|
+
runId: error.conflictingRunId
|
|
108
|
+
};
|
|
97
109
|
}
|
|
98
110
|
throw error; // Re-throw other errors
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
113
|
```
|
|
102
114
|
|
|
103
|
-
This pattern is useful when you want to detect
|
|
115
|
+
This pattern is useful when you want to detect duplicate processing inside the workflow. Runtime APIs such as `resumeHook()` and `getRun()` must be called outside workflow functions, for example from an API route or in a step.
|
|
116
|
+
|
|
117
|
+
### Delegate to the active Run
|
|
118
|
+
|
|
119
|
+
In idempotency flows, a conflict means another active run already owns the hook token. You can return the duplicate-processing payload from the workflow, resume the active hook to deliver the payload to the existing run, then use `getRun(result.runId)` to wait for, stream, or cancel the active run:
|
|
120
|
+
|
|
121
|
+
```typescript lineNumbers
|
|
122
|
+
import { getRun, resumeHook, start } from "workflow/api";
|
|
123
|
+
import { processPayment } from "@/workflows/process-payment";
|
|
124
|
+
|
|
125
|
+
type ProcessPaymentResult =
|
|
126
|
+
| { success: true; payment: unknown }
|
|
127
|
+
| {
|
|
128
|
+
success: false;
|
|
129
|
+
reason: "duplicate-processing";
|
|
130
|
+
token: string;
|
|
131
|
+
runId?: string;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export async function POST(request: Request) {
|
|
135
|
+
const { orderId, payment } = await request.json();
|
|
136
|
+
const run = await start(processPayment, [orderId]);
|
|
137
|
+
const result = (await run.returnValue) as ProcessPaymentResult;
|
|
138
|
+
|
|
139
|
+
if (
|
|
140
|
+
result.success === false &&
|
|
141
|
+
result.reason === "duplicate-processing" &&
|
|
142
|
+
result.runId
|
|
143
|
+
) {
|
|
144
|
+
await resumeHook(result.token, payment); // [!code highlight]
|
|
145
|
+
const activeRun = getRun(result.runId); // [!code highlight]
|
|
146
|
+
|
|
147
|
+
return Response.json({
|
|
148
|
+
delegatedToRunId: activeRun.runId,
|
|
149
|
+
result: await activeRun.returnValue
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return Response.json(result);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
If the caller needs live output instead of the final result, return `activeRun.getReadable()` from the same branch. If the duplicate request should replace the active work, call `await activeRun.cancel()` after inspecting the run.
|
|
104
158
|
|
|
105
|
-
## When
|
|
159
|
+
## When hook tokens are released
|
|
106
160
|
|
|
107
161
|
Hook tokens are automatically released when:
|
|
108
162
|
|
|
109
163
|
- The workflow run **completes** (successfully or with an error)
|
|
110
|
-
- The workflow run is **
|
|
164
|
+
- The workflow run is **canceled**
|
|
111
165
|
- The hook is explicitly **disposed**
|
|
112
166
|
|
|
113
167
|
After a workflow completes, its hook tokens become available for reuse by other workflows.
|
|
114
168
|
|
|
115
|
-
## Best
|
|
169
|
+
## Best practices
|
|
116
170
|
|
|
117
171
|
1. **Use auto-generated tokens** when possible - they are guaranteed to be unique
|
|
118
172
|
2. **Include unique identifiers** if you need custom tokens (order ID, user ID, etc.)
|
|
@@ -122,4 +176,6 @@ After a workflow completes, its hook tokens become available for reuse by other
|
|
|
122
176
|
## Related
|
|
123
177
|
|
|
124
178
|
- [Hooks](/docs/foundations/hooks) - Learn more about using hooks in workflows
|
|
179
|
+
- [getRun](/docs/api-reference/workflow-api/get-run) - Retrieve or control the active run
|
|
180
|
+
- [resumeHook](/docs/api-reference/workflow-api/resume-hook) - Deliver data to the active hook
|
|
125
181
|
- [createWebhook](/docs/api-reference/workflow/create-webhook) - Alternative for fixed webhook URLs
|
package/docs/errors/index.mdx
CHANGED
|
@@ -9,43 +9,9 @@ related:
|
|
|
9
9
|
|
|
10
10
|
Fix common mistakes when creating and executing workflows in the **Workflow SDK**.
|
|
11
11
|
|
|
12
|
-
<
|
|
13
|
-
<Card href="/docs/errors/fetch-in-workflow" title="fetch-in-workflow">
|
|
14
|
-
Learn how to use fetch in workflow functions.
|
|
15
|
-
</Card>
|
|
16
|
-
<Card href="/docs/errors/hook-conflict" title="hook-conflict">
|
|
17
|
-
Learn how to handle hook token conflicts between workflows.
|
|
18
|
-
</Card>
|
|
19
|
-
<Card href="/docs/errors/node-js-module-in-workflow" title="node-js-module-in-workflow">
|
|
20
|
-
Learn how to use Node.js modules in workflows.
|
|
21
|
-
</Card>
|
|
22
|
-
<Card href="/docs/errors/serialization-failed" title="serialization-failed">
|
|
23
|
-
Learn how to handle serialization failures in workflows.
|
|
24
|
-
</Card>
|
|
25
|
-
<Card href="/docs/errors/start-invalid-workflow-function" title="start-invalid-workflow-function">
|
|
26
|
-
Learn how to start an invalid workflow function.
|
|
27
|
-
</Card>
|
|
28
|
-
<Card href="/docs/errors/timeout-in-workflow" title="timeout-in-workflow">
|
|
29
|
-
Learn how to handle timing delays in workflow functions.
|
|
30
|
-
</Card>
|
|
31
|
-
<Card href="/docs/errors/webhook-invalid-respond-with-value" title="webhook-invalid-respond-with-value">
|
|
32
|
-
Learn how to use the correct `respondWith` values for webhooks.
|
|
33
|
-
</Card>
|
|
34
|
-
<Card href="/docs/errors/webhook-response-not-sent" title="webhook-response-not-sent">
|
|
35
|
-
Learn how to send responses when using manual webhook response mode.
|
|
36
|
-
</Card>
|
|
37
|
-
<Card href="/docs/errors/corrupted-event-log" title="corrupted-event-log">
|
|
38
|
-
Learn how to handle corrupted or invalid event logs.
|
|
39
|
-
</Card>
|
|
40
|
-
<Card href="/docs/errors/step-not-registered" title="step-not-registered">
|
|
41
|
-
Resolve step not registered errors caused by deployment mismatches.
|
|
42
|
-
</Card>
|
|
43
|
-
<Card href="/docs/errors/workflow-not-registered" title="workflow-not-registered">
|
|
44
|
-
Resolve workflow not registered errors caused by deployment mismatches.
|
|
45
|
-
</Card>
|
|
46
|
-
</Cards>
|
|
12
|
+
<AutoCards />
|
|
47
13
|
|
|
48
|
-
## Learn
|
|
14
|
+
## Learn more
|
|
49
15
|
|
|
50
16
|
* [API Reference](/docs/api-reference) - Complete API documentation
|
|
51
17
|
* [Foundations](/docs/foundations) - Architecture and core concepts
|
|
@@ -9,21 +9,25 @@ related:
|
|
|
9
9
|
- /docs/how-it-works/understanding-directives
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="Fix Node.js module usage inside workflow functions. Search workflow files for imports or direct usage of Node-only APIs such as `fs`, `path`, `crypto`, `process`, `http`, or SDK clients. Remove those imports from files/functions that execute under `"use workflow"`. Create helper functions with `"use step"` for filesystem, crypto, environment, network, database, or SDK work, and call those helpers from the workflow. Keep the workflow function limited to deterministic orchestration, serializable values, `sleep`, hooks, and step calls. Verify the workflow starts without node-js-module-in-workflow errors."
|
|
14
|
+
/>
|
|
15
|
+
|
|
12
16
|
This error occurs when you try to import or use Node.js core modules (like `fs`, `http`, `crypto`, `path`, etc.) directly inside a workflow function.
|
|
13
17
|
|
|
14
|
-
## Error
|
|
18
|
+
## Error message
|
|
15
19
|
|
|
16
|
-
```
|
|
20
|
+
```text
|
|
17
21
|
Cannot use Node.js module "fs" in workflow functions. Move this module to a step function.
|
|
18
22
|
```
|
|
19
23
|
|
|
20
|
-
## Why
|
|
24
|
+
## Why this happens
|
|
21
25
|
|
|
22
26
|
Workflow functions run in a sandboxed environment without full Node.js runtime access. This restriction is important for maintaining **determinism** - the ability to replay workflows exactly and resume from where they left off after suspensions or failures.
|
|
23
27
|
|
|
24
28
|
Node.js modules have side effects and non-deterministic behavior that could break workflow replay guarantees.
|
|
25
29
|
|
|
26
|
-
## Quick
|
|
30
|
+
## Quick fix
|
|
27
31
|
|
|
28
32
|
Move any code using Node.js modules to a step function. Step functions have full Node.js runtime access.
|
|
29
33
|
|
|
@@ -64,7 +68,7 @@ async function read(filePath: string) {
|
|
|
64
68
|
}
|
|
65
69
|
```
|
|
66
70
|
|
|
67
|
-
## Common Node.js
|
|
71
|
+
## Common Node.js modules
|
|
68
72
|
|
|
69
73
|
These common Node.js core modules cannot be used in workflow functions:
|
|
70
74
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: replay-divergence
|
|
3
|
+
description: A workflow replay temporarily followed a path that did not match its recorded events.
|
|
4
|
+
type: troubleshooting
|
|
5
|
+
summary: Understand automatic recovery when a workflow replay diverges from its event history.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/errors/corrupted-event-log
|
|
10
|
+
- /docs/foundations/errors-and-retries
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
A replay divergence occurs when one invocation of a workflow cannot consume the durable event history using the promises, hooks, sleeps, or steps it created during replay.
|
|
14
|
+
|
|
15
|
+
This is an SDK/runtime signal, not an error thrown by your workflow code. It is not catchable inside a workflow function.
|
|
16
|
+
|
|
17
|
+
## Automatic recovery
|
|
18
|
+
|
|
19
|
+
A single divergent replay does not prove that persisted history is corrupted. For example, asynchronous delivery ordering may cause one invocation to follow the wrong side of a race while another replay can follow the recorded history correctly.
|
|
20
|
+
|
|
21
|
+
The runtime automatically queues another replay when an invocation reports `REPLAY_DIVERGENCE`. No terminal `run_failed` event is written during these recovery attempts.
|
|
22
|
+
|
|
23
|
+
If recovery replays continue to diverge after the recovery budget is exhausted, the runtime marks the run as failed with `CORRUPTED_EVENT_LOG` and records the latest divergent event for diagnosis.
|
|
24
|
+
|
|
25
|
+
## What to do
|
|
26
|
+
|
|
27
|
+
Most replay divergence signals recover without action. If a run ultimately fails with `CORRUPTED_EVENT_LOG`, update to the latest `workflow` package and report the run ID and error details if the failure persists.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: run-expired
|
|
3
|
+
description: A run's data passed its retention boundary, so its result can no longer be read.
|
|
4
|
+
type: troubleshooting
|
|
5
|
+
summary: Read a run's result before it expires, or return it through a channel you control.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/observability/retention
|
|
10
|
+
- /docs/api-reference/workflow-api/start
|
|
11
|
+
- /docs/foundations/hooks
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Error
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
Run "wrun_..." completed, but its data expired at 2026-08-28T05:02:35.009Z
|
|
18
|
+
and is no longer readable.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Thrown as a `RunExpiredError` from `await run.returnValue`.
|
|
22
|
+
|
|
23
|
+
## Why this happens
|
|
24
|
+
|
|
25
|
+
A run's payloads — its input, output and error, and those of its steps — are
|
|
26
|
+
kept only for as long as the World's retention policy says. Its *metadata* —
|
|
27
|
+
id, status, timestamps — usually outlives them. So a run can be readable as a
|
|
28
|
+
record while its result is already gone.
|
|
29
|
+
|
|
30
|
+
Rather than hand back a placeholder that is indistinguishable from a value the
|
|
31
|
+
workflow genuinely returned, `returnValue` throws.
|
|
32
|
+
|
|
33
|
+
Two ways to reach it:
|
|
34
|
+
|
|
35
|
+
- **The run was started with `experimental_retention: 0`.** Its data is
|
|
36
|
+
deleted the moment it reaches a terminal state, and that deletion races your
|
|
37
|
+
own read of the result — and generally wins. On these runs, expect this
|
|
38
|
+
error rather than treating it as an edge case. See
|
|
39
|
+
[Data retention](/docs/observability/retention).
|
|
40
|
+
- **The run simply aged out.** It finished long enough ago that the World's
|
|
41
|
+
default retention window has passed.
|
|
42
|
+
|
|
43
|
+
## How to respond
|
|
44
|
+
|
|
45
|
+
`RunExpiredError` is terminal. Retrying will not bring the data back, so catch
|
|
46
|
+
Catch the error and use the run's metadata to decide what you want to do.
|
|
47
|
+
|
|
48
|
+
```typescript lineNumbers
|
|
49
|
+
import { getRun } from "workflow/api"
|
|
50
|
+
import { RunExpiredError } from "workflow/errors"
|
|
51
|
+
|
|
52
|
+
export async function readResult(runId: string) {
|
|
53
|
+
try {
|
|
54
|
+
return await getRun(runId).returnValue
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (RunExpiredError.is(error)) { // [!code highlight]
|
|
57
|
+
// `runStatus` is the run's terminal status when the World still has
|
|
58
|
+
// it, so you can tell a successful run whose result is gone from a
|
|
59
|
+
// failed one whose error is gone.
|
|
60
|
+
if (error.runStatus === "completed") {
|
|
61
|
+
// The run succeeded; its result is simply no longer stored.
|
|
62
|
+
}
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
throw error
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The error carries `runId`, `runStatus` and `expiredAt` when the World reports
|
|
71
|
+
them.
|
|
72
|
+
|
|
73
|
+
### If you need the result of a zero-retention run
|
|
74
|
+
|
|
75
|
+
Do not read it back off the run. Send it somewhere you control while the run
|
|
76
|
+
is still executing — a step that writes it to your own store. That is the intended pattern
|
|
77
|
+
for `experimental_retention: 0`: the point of the option is that the platform
|
|
78
|
+
does not keep your data, so the platform cannot also be where you fetch it
|
|
79
|
+
from afterwards.
|
|
80
|
+
|
|
81
|
+
## Related
|
|
82
|
+
|
|
83
|
+
If the run is gone entirely — metadata included — the World reports it as
|
|
84
|
+
missing and you get a `WorkflowRunNotFoundError` instead. That means the
|
|
85
|
+
record itself has been cleaned up, not just its payloads.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: runtime-decryption-failed
|
|
3
|
+
description: The SDK's built-in AES-GCM encryption layer failed to encrypt or decrypt a workflow payload.
|
|
4
|
+
type: troubleshooting
|
|
5
|
+
summary: Resolve runtime decryption failures caused by ciphertext corruption, key mismatch, or malformed envelopes.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations/errors-and-retries
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
This error occurs when the Workflow SDK's built-in AES-GCM encryption layer fails while encrypting or decrypting a workflow payload. The SDK encrypts step inputs, step outputs, hook payloads, and other event-log data with a per-run AES-256 key whenever encryption is configured for the deployment.
|
|
13
|
+
|
|
14
|
+
This is an **internal SDK failure**: your workflow code never invokes the encryption primitives directly. When this surfaces, the ciphertext, nonce, or authentication tag the SDK tried to verify does not match the bytes that were originally produced. The run fails with the `RUNTIME_ERROR` classification.
|
|
15
|
+
|
|
16
|
+
## Error message
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
AES-256-GCM decryption failed: The operation failed for an operation-specific reason
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The underlying cause is a native Web Crypto [`OperationError`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException#operationerror), most commonly raised by `AESCipherJob.onDone` in Node's `node:internal/crypto/util` module when the GCM authentication tag does not verify.
|
|
23
|
+
|
|
24
|
+
The thrown `RuntimeDecryptionError` carries a small `context` object with diagnostic fields to help triangulate the source:
|
|
25
|
+
|
|
26
|
+
- `operation`: `'encrypt'` or `'decrypt'`
|
|
27
|
+
- `byteLength`: total byte length of the payload at the failure site
|
|
28
|
+
- `formatPrefix`: the first 4 bytes of the input (`'encr'` for a well-formed encrypted envelope, otherwise a hex dump)
|
|
29
|
+
|
|
30
|
+
## Why this happens
|
|
31
|
+
|
|
32
|
+
Common causes, in rough order of likelihood:
|
|
33
|
+
|
|
34
|
+
1. **Ciphertext mutation or truncation in transit.** The encrypted payload reached the SDK with bytes that differ from what storage holds. Possible sources include a truncated HTTP response from a workflow-server ref endpoint, an edge-cache miss returning a partial 200, or a proxy drop during streaming. A truncated body whose first 4 bytes happen to still spell `encr` produces the exact "auth tag mismatch" symptom.
|
|
35
|
+
2. **Key resolution mismatch.** The key used to decrypt is not the key that was used to encrypt, e.g. the run's `deploymentId` was not threaded through key resolution and the SDK fell back to the wrong deployment's key material.
|
|
36
|
+
3. **Malformed encrypted envelope.** The envelope is too short to contain the GCM nonce (12 bytes) and auth tag (16 bytes), so decryption is rejected before it begins.
|
|
37
|
+
|
|
38
|
+
## What to do
|
|
39
|
+
|
|
40
|
+
This error indicates an SDK or infrastructure problem, not a bug in your workflow code. Your workflow code does not need to change.
|
|
41
|
+
|
|
42
|
+
### 1. Upgrade to the latest `workflow` package
|
|
43
|
+
|
|
44
|
+
The underlying issue may have already been identified and fixed:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install workflow@latest
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Retry the failed run
|
|
51
|
+
|
|
52
|
+
Since this is a fatal error, the run is automatically marked as `failed`. You can re-run it using the **Re-run** button in the Workflow Dashboard.
|
|
53
|
+
|
|
54
|
+
### 3. Report the issue
|
|
55
|
+
|
|
56
|
+
If the error persists after upgrading, please [open an issue on GitHub](https://github.com/vercel/workflow/issues/new) so we can investigate. Include:
|
|
57
|
+
|
|
58
|
+
- The version of the `workflow` package you are using
|
|
59
|
+
- The run ID(s) of the affected workflow run(s)
|
|
60
|
+
- The full error message, including the `context` fields (`operation`, `byteLength`, `formatPrefix`)
|
|
61
|
+
- Whether the affected workflows make heavy use of large step inputs/outputs (which may indicate the failure is on the lazy-loaded ref read path)
|
|
62
|
+
|
|
63
|
+
## This error cannot be caught
|
|
64
|
+
|
|
65
|
+
Like other `WorkflowRuntimeError` subclasses, a runtime decryption failure is **not catchable** inside your workflow function. The runtime cannot safely continue executing user code when an event-log payload can't be verified, so the entire run fails immediately and is marked as `failed`.
|
|
66
|
+
|
|
67
|
+
To handle this programmatically from outside the workflow, check the run status:
|
|
68
|
+
|
|
69
|
+
```typescript lineNumbers
|
|
70
|
+
import { getRun } from "workflow/api";
|
|
71
|
+
|
|
72
|
+
const run = getRun("wrun_abc123");
|
|
73
|
+
const status = await run.status;
|
|
74
|
+
if (status === "failed") {
|
|
75
|
+
console.error("Run failed");
|
|
76
|
+
}
|
|
77
|
+
```
|
|
@@ -9,11 +9,15 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="Fix Workflow serialization errors. Find the failing `start()` call, workflow argument, step return value, hook payload, or stream chunk. Replace non-serializable values such as class instances, functions, SDK clients, Response/Request objects, streams, database connections, Dates that need custom handling, Maps/Sets, or circular objects with plain JSON-compatible data, IDs, strings, numbers, booleans, arrays, and objects. Recreate runtime-only clients or objects inside `"use step"` helpers instead of passing them through the workflow log. For external resources, pass a stable ID or URL and load the resource inside the step. Add a test or local route call that serializes the same input/output path successfully."
|
|
14
|
+
/>
|
|
15
|
+
|
|
12
16
|
This error occurs when you try to pass non-serializable data between execution boundaries in your workflow. All data passed between workflow functions, step functions, and the workflow runtime must be serializable to persist in the event log.
|
|
13
17
|
|
|
14
|
-
## Error
|
|
18
|
+
## Error message
|
|
15
19
|
|
|
16
|
-
```
|
|
20
|
+
```text
|
|
17
21
|
Failed to serialize workflow arguments. Ensure you're passing serializable types
|
|
18
22
|
(plain objects, arrays, primitives, Date, RegExp, Map, Set).
|
|
19
23
|
```
|
|
@@ -25,7 +29,35 @@ This error can appear when:
|
|
|
25
29
|
- Serializing step arguments
|
|
26
30
|
- Serializing step return values
|
|
27
31
|
|
|
28
|
-
##
|
|
32
|
+
## Where the error surfaces
|
|
33
|
+
|
|
34
|
+
Where you observe the failure depends on which boundary it crosses:
|
|
35
|
+
|
|
36
|
+
- **Workflow arguments**: `start()` throws synchronously in your application code.
|
|
37
|
+
- **Step arguments and step return values**: the *step* fails with the `SerializationError`, exactly like a step whose body threw a fatal error: no retries (the failure is deterministic), and a `try/catch` around the step call in your workflow code observes it. The step's recorded input shows `[input unavailable: step argument serialization failed]` when the arguments were the unserializable part.
|
|
38
|
+
- **Workflow return values**: the workflow body has already returned, so nothing can catch it; the run fails.
|
|
39
|
+
|
|
40
|
+
```typescript lineNumbers
|
|
41
|
+
async function stepWithBadArguments(value: unknown) {
|
|
42
|
+
"use step";
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function processWorkflow(someValue: unknown) {
|
|
47
|
+
"use workflow";
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
await stepWithBadArguments(someValue);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
// err.name === "SerializationError"
|
|
53
|
+
// "Failed to serialize step arguments at path ..."
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Uncaught, the error propagates out of the workflow body and the run fails immediately with the error code `USER_ERROR`; it does not retry.
|
|
59
|
+
|
|
60
|
+
## Why this happens
|
|
29
61
|
|
|
30
62
|
Workflows persist their state using an event log. Every value that crosses execution boundaries must be:
|
|
31
63
|
|
|
@@ -34,9 +66,9 @@ Workflows persist their state using an event log. Every value that crosses execu
|
|
|
34
66
|
|
|
35
67
|
Functions, class instances, symbols, and other non-serializable types cannot be properly reconstructed after serialization, which would break workflow replay.
|
|
36
68
|
|
|
37
|
-
## Common
|
|
69
|
+
## Common causes
|
|
38
70
|
|
|
39
|
-
### Passing
|
|
71
|
+
### Passing functions
|
|
40
72
|
|
|
41
73
|
{/* @skip-typecheck: incomplete code sample */}
|
|
42
74
|
```typescript lineNumbers
|
|
@@ -68,7 +100,7 @@ async function processStep(config: { shouldLog: boolean }) {
|
|
|
68
100
|
}
|
|
69
101
|
```
|
|
70
102
|
|
|
71
|
-
### Class
|
|
103
|
+
### Class instances
|
|
72
104
|
|
|
73
105
|
```typescript lineNumbers
|
|
74
106
|
class User {
|
|
@@ -107,11 +139,11 @@ async function greetStep(userData: { name: string }) {
|
|
|
107
139
|
}
|
|
108
140
|
```
|
|
109
141
|
|
|
110
|
-
## Supported
|
|
142
|
+
## Supported serializable types
|
|
111
143
|
|
|
112
144
|
Workflow SDK supports these types across execution boundaries:
|
|
113
145
|
|
|
114
|
-
### Standard JSON
|
|
146
|
+
### Standard JSON types
|
|
115
147
|
|
|
116
148
|
- `string`, `number`, `boolean`, `null`
|
|
117
149
|
- Arrays of serializable values
|
|
@@ -119,10 +151,10 @@ Workflow SDK supports these types across execution boundaries:
|
|
|
119
151
|
|
|
120
152
|
To learn more about supported types, see the [Serialization](/docs/foundations/serialization) section.
|
|
121
153
|
|
|
122
|
-
## Debugging
|
|
154
|
+
## Debugging serialization issues
|
|
123
155
|
|
|
124
156
|
To identify what's causing serialization to fail:
|
|
125
157
|
|
|
126
|
-
1. **Check the error stack trace
|
|
127
|
-
2. **Simplify your data
|
|
128
|
-
3. **
|
|
158
|
+
1. **Check the error stack trace**: It often shows which property failed.
|
|
159
|
+
2. **Simplify your data**: Temporarily pass smaller objects to isolate the issue.
|
|
160
|
+
3. **Use supported data types**: See [Serialization](/docs/foundations/serialization) for details.
|
|
@@ -11,19 +11,23 @@ related:
|
|
|
11
11
|
- /docs/api-reference/workflow-next/with-workflow
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
<CopyPrompt
|
|
15
|
+
text="Fix `start()` receiving an invalid workflow function. Find the function passed to `start()` from `workflow/api`. Ensure the target function is directly imported, exported from its workflow file, and contains the literal `"use workflow"` directive at the top of the function body. Do not pass wrapper callbacks like `start(async () => workflowFn())`; call `start(workflowFn, [args])`. Verify the framework integration is configured (`withWorkflow()` in Next.js, `workflow()`/`workflowPlugin()` in Vite/Astro/SvelteKit, `workflow/nitro`, `workflow/nuxt`, or `@workflow/nest` as appropriate) and that the workflow file is inside a transformed directory. Add a local route/test that calls `start(workflowFn, args)` and confirms a run is created."
|
|
16
|
+
/>
|
|
17
|
+
|
|
14
18
|
This error occurs when `start()` receives a function that does not have Workflow SDK's generated workflow metadata. In practice, that usually means the function is missing `"use workflow"` or the file was never transformed by your framework integration.
|
|
15
19
|
|
|
16
|
-
## Error
|
|
20
|
+
## Error message
|
|
17
21
|
|
|
18
|
-
```
|
|
22
|
+
```text
|
|
19
23
|
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
20
24
|
```
|
|
21
25
|
|
|
22
|
-
## Why
|
|
26
|
+
## Why this happens
|
|
23
27
|
|
|
24
|
-
`start()` expects an imported workflow function
|
|
28
|
+
`start()` expects an imported workflow function rather than any async function. During compilation, Workflow SDK transforms files that contain `"use workflow"` and attaches generated metadata such as the workflow ID. If that transform never runs, or if you pass a wrapper function instead of the transformed export, `start()` cannot identify what to enqueue and throws this error.
|
|
25
29
|
|
|
26
|
-
## Common
|
|
30
|
+
## Common causes
|
|
27
31
|
|
|
28
32
|
### Missing `"use workflow"`
|
|
29
33
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Step executed multiple times
|
|
3
|
+
description: A step ran more than once because its function invocation crashed before it could report a result.
|
|
4
|
+
type: troubleshooting
|
|
5
|
+
summary: Diagnose duplicate step_started events caused by function timeouts, OOMs, or network issues.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/observability
|
|
10
|
+
- /docs/foundations/errors-and-retries
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
There may be cases where you see multiple `step_started` events for the same step in a workflow run. This happens if the function invocation executing the step crashes unexpectedly, and the step can not report the error. The step will be re-tried according to your retry policy in this case, but no error will be visible in the [Observability UI](/docs/observability).
|
|
14
|
+
|
|
15
|
+
## Common causes
|
|
16
|
+
|
|
17
|
+
- **Function timeouts**: if your step code runs longer than the configured maximum function duration, it will be killed. Compare the gap between the `step_started` events to your configured function duration to be sure.
|
|
18
|
+
- **Out of memory (OOM)**: if your step code loads enough data into memory, especially if the step is invoked concurrently, the function invocation might run out of memory. You can see your function's peak memory use by going to the [Observability Query page](https://vercel.com/docs/observability) and showing the **Function Invocation Peak Memory** metric, then filtering down the **Route** to `/.well-known/workflow` endpoints.
|
|
19
|
+
- **Network issues**: persistent firewall, network stability, and related issues might prevent your function from reporting results or errors. This should be temporary.
|
|
20
|
+
|
|
21
|
+
## Getting help
|
|
22
|
+
|
|
23
|
+
If you consistently see multiple `step_started` events and have ruled out function timeouts, OOMs, and firewall issues, please [contact support](https://vercel.com/help).
|
|
@@ -4,7 +4,7 @@ description: A step function is not registered in the current deployment.
|
|
|
4
4
|
type: troubleshooting
|
|
5
5
|
summary: Resolve step not registered errors caused by build issues.
|
|
6
6
|
prerequisites:
|
|
7
|
-
- /docs/foundations/steps
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
8
|
related:
|
|
9
9
|
- /docs/errors/workflow-not-registered
|
|
10
10
|
- /docs/api-reference/workflow-errors/step-not-registered-error
|
|
@@ -12,21 +12,21 @@ related:
|
|
|
12
12
|
|
|
13
13
|
This error occurs when the Workflow runtime tries to execute a step function that is not registered in the current deployment. When this happens, the step fails (like a `FatalError`) and control is passed back to the workflow function, which can optionally handle the failure.
|
|
14
14
|
|
|
15
|
-
## Error
|
|
15
|
+
## Error message
|
|
16
16
|
|
|
17
|
-
```
|
|
17
|
+
```text
|
|
18
18
|
Step "<stepName>" is not registered in the current deployment.
|
|
19
19
|
This usually indicates a build or bundling issue that caused the step
|
|
20
20
|
to not be included in the deployment.
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## Why
|
|
23
|
+
## Why this happens
|
|
24
24
|
|
|
25
25
|
Workflow runs are pegged to a specific deployment, so this error is not caused by newer deployments overriding the running code. Instead, it means the step function was not included in the deployment's workflow bundle at build time.
|
|
26
26
|
|
|
27
27
|
This is an **infrastructure error**, not a user code error.
|
|
28
28
|
|
|
29
|
-
## Common
|
|
29
|
+
## Common causes
|
|
30
30
|
|
|
31
31
|
### Build tooling issue
|
|
32
32
|
|
|
@@ -40,7 +40,7 @@ Something went wrong during the build process that caused the step function to n
|
|
|
40
40
|
|
|
41
41
|
The step function was deleted or its `"use step"` directive was removed, but the workflow still references it. Ensure all steps referenced by your workflow are present in the codebase.
|
|
42
42
|
|
|
43
|
-
## How to
|
|
43
|
+
## How to resolve
|
|
44
44
|
|
|
45
45
|
1. **Check your build logs:** Look for errors or warnings related to workflow bundling. Ensure the step file contains a valid `"use step"` directive and is properly exported.
|
|
46
46
|
|