Skip to content

Proper error stack propogating#280

Merged
pranaygp merged 6 commits into
mainfrom
pranaygp/proper-error-stack-propogation
Nov 11, 2025
Merged

Proper error stack propogating#280
pranaygp merged 6 commits into
mainfrom
pranaygp/proper-error-stack-propogation

Conversation

@pranaygp
Copy link
Copy Markdown
Contributor

@pranaygp pranaygp commented Nov 8, 2025

In #256 we started propogating error stacks for worklfow runs, but we just marshalled them into the error string itself. This now moves the stack propogation more correctly into the world interface instead :)


This is part 2 of 3 in a stack made with GitButler:

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Nov 8, 2025

🦋 Changeset detected

Latest commit: e6e749e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
@workflow/world-local Patch
@workflow/web-shared Patch
@workflow/core Patch
@workflow/world-postgres Patch
@workflow/errors Patch
@workflow/world Patch
@workflow/world-vercel Patch
@workflow/cli Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
workflow Patch
@workflow/world-testing Patch
@workflow/sveltekit Patch
@workflow/nuxt Patch
@workflow/ai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Nov 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview Comment Nov 11, 2025 11:23pm
example-nextjs-workflow-webpack Ready Ready Preview Comment Nov 11, 2025 11:23pm
example-workflow Ready Ready Preview Comment Nov 11, 2025 11:23pm
workbench-hono-workflow Ready Ready Preview Comment Nov 11, 2025 11:23pm
workbench-nitro-workflow Ready Ready Preview Comment Nov 11, 2025 11:23pm
workbench-nuxt-workflow Ready Ready Preview Comment Nov 11, 2025 11:23pm
workbench-sveltekit-workflow Ready Ready Preview Comment Nov 11, 2025 11:23pm
workbench-vite-workflow Ready Ready Preview Comment Nov 11, 2025 11:23pm
workflow-docs Ready Ready Preview Comment Nov 11, 2025 11:23pm

@pranaygp pranaygp force-pushed the copilot/fix-sourcemap-tracking branch from 3ffca64 to 9a850c8 Compare November 8, 2025 17:28
@pranaygp pranaygp force-pushed the pranaygp/proper-error-stack-propogation branch from b8b3245 to ba2e061 Compare November 8, 2025 17:28
Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The attributeToDisplayFn object is missing a handler for the errorStack property, causing TypeScript to fail compilation since errorStack is included in the AttributeKey type union but not implemented in the mapping object.

View Details
📝 Patch Details
diff --git a/packages/web-shared/src/sidebar/attribute-panel.tsx b/packages/web-shared/src/sidebar/attribute-panel.tsx
index b12fbaf..073ec82 100644
--- a/packages/web-shared/src/sidebar/attribute-panel.tsx
+++ b/packages/web-shared/src/sidebar/attribute-panel.tsx
@@ -53,6 +53,7 @@ const attributeOrder: AttributeKey[] = [
   'completedAt',
   'retryAfter',
   'error',
+  'errorStack',
   'errorCode',
   'metadata',
   'eventData',
@@ -125,6 +126,9 @@ const attributeToDisplayFn: Record<
   error: (value: unknown) => {
     return <DetailCard summary="Error">{JsonBlock(value)}</DetailCard>;
   },
+  errorStack: (value: unknown) => {
+    return <DetailCard summary="Error Stack">{JsonBlock(value)}</DetailCard>;
+  },
   errorCode: JsonBlock,
   eventData: (value: unknown) => {
     return <DetailCard summary="Event Data">{JsonBlock(value)}</DetailCard>;
@@ -135,6 +139,7 @@ const resolvableAttributes = [
   'input',
   'output',
   'error',
+  'errorStack',
   'errorCode',
   'metadata',
   'eventData',

Analysis

Missing TypeScript handler for errorStack property causes compilation failure

What fails: TypeScript compiler fails on packages/web-shared/src/sidebar/attribute-panel.tsx at line 70 due to missing errorStack property handler in attributeToDisplayFn object

How to reproduce:

cd packages/web-shared && pnpm run build

Result:

src/sidebar/attribute-panel.tsx(70,7): error TS2741: Property 'errorStack' is missing in type '{ workflowName: (value: unknown) => string; stepName: (value: unknown) => string; runId: (value: unknown) => string; stepId: (value: unknown) => string; hookId: (value: unknown) => string; ... 22 more ...; eventData: (value: unknown) => JSX.Element; }' but required in type 'Record<AttributeKey, (value: unknown) => ReactNode>'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The attributeToDisplayFn record was missing a display function for the errorStack property, which is required by the TypeScript type system since errorStack is part of both Step and WorkflowRun types.

View Details
📝 Patch Details
diff --git a/packages/web-shared/src/sidebar/attribute-panel.tsx b/packages/web-shared/src/sidebar/attribute-panel.tsx
index b12fbaf..c649e4d 100644
--- a/packages/web-shared/src/sidebar/attribute-panel.tsx
+++ b/packages/web-shared/src/sidebar/attribute-panel.tsx
@@ -125,6 +125,9 @@ const attributeToDisplayFn: Record<
   error: (value: unknown) => {
     return <DetailCard summary="Error">{JsonBlock(value)}</DetailCard>;
   },
+  errorStack: (value: unknown) => {
+    return <DetailCard summary="Error Stack">{JsonBlock(value)}</DetailCard>;
+  },
   errorCode: JsonBlock,
   eventData: (value: unknown) => {
     return <DetailCard summary="Event Data">{JsonBlock(value)}</DetailCard>;

Analysis

Missing errorStack property causes TypeScript compilation failure

What fails: TypeScript compiler fails on packages/web-shared/src/sidebar/attribute-panel.tsx line 70 due to missing errorStack property in attributeToDisplayFn record

How to reproduce:

cd packages/web-shared && pnpm run build

Result:

src/sidebar/attribute-panel.tsx(70,7): error TS2741: Property 'errorStack' is missing in type '{ workflowName: (value: unknown) => string; stepName: (value: unknown) => string; runId: (value: unknown) => string; stepId: (value: unknown) => string; hookId: (value: unknown) => string; ... 22 more ...; eventData: (value: unknown) => JSX.Element; }' but required in type 'Record<AttributeKey, (value: unknown) => ReactNode>'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The attributeToDisplayFn object is missing the errorStack property that is required by the AttributeKey type, causing TypeScript compilation to fail.

View Details
📝 Patch Details
diff --git a/packages/web-shared/src/sidebar/attribute-panel.tsx b/packages/web-shared/src/sidebar/attribute-panel.tsx
index b12fbaf..f3bb0b4 100644
--- a/packages/web-shared/src/sidebar/attribute-panel.tsx
+++ b/packages/web-shared/src/sidebar/attribute-panel.tsx
@@ -125,6 +125,9 @@ const attributeToDisplayFn: Record<
   error: (value: unknown) => {
     return <DetailCard summary="Error">{JsonBlock(value)}</DetailCard>;
   },
+  errorStack: (value: unknown) => {
+    return <DetailCard summary="Error Stack">{JsonBlock(value)}</DetailCard>;
+  },
   errorCode: JsonBlock,
   eventData: (value: unknown) => {
     return <DetailCard summary="Event Data">{JsonBlock(value)}</DetailCard>;
@@ -135,6 +138,7 @@ const resolvableAttributes = [
   'input',
   'output',
   'error',
+  'errorStack',
   'errorCode',
   'metadata',
   'eventData',

Analysis

Missing errorStack property in attributeToDisplayFn causes TypeScript compilation failure

What fails: TypeScript compiler fails on src/sidebar/attribute-panel.tsx at line 70 due to missing errorStack property in attributeToDisplayFn object

How to reproduce:

cd packages/web-shared && pnpm run build

Result:

src/sidebar/attribute-panel.tsx(70,7): error TS2741: Property 'errorStack' is missing in type '{ workflowName: (value: unknown) => string; stepName: (value: unknown) => string; runId: (value: unknown) => string; stepId: (value: unknown) => string; hookId: (value: unknown) => string; ... 22 more ...; eventData: (value: unknown) => JSX.Element; }' but required in type 'Record<AttributeKey, (value: unknown) => ReactNode>'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

The FatalError event data uses err.stack directly instead of the extracted errorStack variable, causing potential data loss and inconsistency with similar error handling code elsewhere.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 01fa238..74ce62e 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -750,7 +750,7 @@ export const stepEntrypoint =
                 correlationId: stepId,
                 eventData: {
                   error: String(err),
-                  stack: err.stack,
+                  stack: errorStack,
                   fatal: true,
                 },
               });

Analysis

Inconsistent error stack handling in FatalError event creation

What fails: In packages/core/src/runtime.ts line 753, the FatalError event uses err.stack directly instead of the extracted errorStack variable, causing potential undefined values in event data.

How to reproduce:

  1. Define a step that throws a non-native error object (e.g., throw { message: "error", isFatal: true })
  2. Wrap it as a FatalError in the workflow
  3. Trigger step execution with this non-native error
  4. Check the event data created by world.events.create()

Result: The event's eventData.stack field is undefined because err.stack is undefined for non-native error objects.

Expected: The event's eventData.stack field should contain the extracted error stack (either the actual stack or an empty string), consistent with:

  • Line 783: stack: errorStack, (max retries case)
  • Line 818: stack: getErrorStack(err), (retryable error case)

The getErrorStack() function in types.ts guarantees a string return (either native error stack or empty string), whereas err.stack can be undefined. The extracted errorStack variable at line 742 was already safely computed but not used in the event.

Fix on Vercel

@pranaygp
Copy link
Copy Markdown
Contributor Author

pranaygp commented Nov 9, 2025

okay @TooTallNate I'm gonna invest the time in to simplify the world to have a single error object in this PR. I've made some process and switched back to draft for now. will complete this and reopen soon

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The build fails because the code assigns errorCode properties to WorkflowRun and Step objects, but these properties don't exist in the TypeScript schemas defined in @workflow/world.

View Details
📝 Patch Details
diff --git a/packages/world-local/src/storage.ts b/packages/world-local/src/storage.ts
index 2292832..7c99382 100644
--- a/packages/world-local/src/storage.ts
+++ b/packages/world-local/src/storage.ts
@@ -112,7 +112,6 @@ export function createStorage(basedir: string): Storage {
           input: (data.input as any[]) || [],
           output: undefined,
           error: undefined,
-          errorCode: undefined,
           startedAt: undefined,
           completedAt: undefined,
           createdAt: now,
@@ -234,7 +233,6 @@ export function createStorage(basedir: string): Storage {
           input: data.input as any[],
           output: undefined,
           error: undefined,
-          errorCode: undefined,
           attempt: 0,
           startedAt: undefined,
           completedAt: undefined,

Analysis

TypeScript compilation fails due to invalid errorCode properties

What fails: TypeScript compiler fails on packages/world-local/src/storage.ts due to errorCode properties not existing in the WorkflowRun and Step schemas

How to reproduce:

pnpm turbo run build --filter=@workflow/world-local

Result:

src/storage.ts(115,11): error TS2353: Object literal may only specify known properties, and 'errorCode' does not exist in type '{ runId: string; deploymentId: string; status: "pending" | "running" | "completed" | "failed" | "paused" | "cancelled"; workflowName: string; input: any[]; createdAt: Date; updatedAt: Date; ... 4 more ...; completedAt?: Date | undefined; }'.
src/storage.ts(237,11): error TS2353: Object literal may only specify known properties, and 'errorCode' does not exist in type '{ runId: string; stepId: string; stepName: string; status: "pending" | "running" | "completed" | "failed" | "cancelled"; input: any[]; attempt: number; createdAt: Date; updatedAt: Date; ... 4 more ...; retryAfter?: Date | undefined; }'.
Fix on Vercel

Comment thread packages/errors/src/index.ts
Comment on lines +125 to +139
return (
<DetailCard summary="Error">
<pre
className="text-copy-12 overflow-x-auto rounded-md border p-4"
style={{
borderColor: 'var(--ds-gray-300)',
backgroundColor: 'var(--ds-gray-100)',
color: 'var(--ds-gray-1000)',
whiteSpace: 'pre-wrap',
}}
>
<code>{String(value)}</code>
</pre>
</DetailCard>
);
Copy link
Copy Markdown
Contributor

@vercel vercel Bot Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return (
<DetailCard summary="Error">
<pre
className="text-copy-12 overflow-x-auto rounded-md border p-4"
style={{
borderColor: 'var(--ds-gray-300)',
backgroundColor: 'var(--ds-gray-100)',
color: 'var(--ds-gray-1000)',
whiteSpace: 'pre-wrap',
}}
>
<code>{String(value)}</code>
</pre>
</DetailCard>
);
return <DetailCard summary="Error">{JsonBlock(value)}</DetailCard>;

The error display function uses String(value) which converts StructuredError objects to [object Object] instead of displaying the actual error information.

View Details

Analysis

Error attribute displays [object Object] instead of error details in AttributePanel

What fails: The error attribute display handler in AttributePanel (packages/web-shared/src/sidebar/attribute-panel.tsx, line 136) uses String(value) on a StructuredError object, which produces [object Object] instead of displaying error information.

How to reproduce:

  1. Display a workflow run or step with an error status in the trace viewer
  2. Navigate to the Error attribute in the detail panel
  3. Observe the error display shows [object Object] instead of the actual error content

Result: Error attribute displays [object Object] with no useful error information

Expected: Should display the error as formatted JSON showing the message, stack, and code properties, consistent with other complex attributes like input, output, and metadata which use JsonBlock()

Root cause: The StructuredError type (defined in packages/world/src/shared.ts as { message: string, stack?: string, code?: string }) is a plain object. When String() is called on a plain object in JavaScript, it returns [object Object]. The previous implementation used JsonBlock(value) which properly serializes the object with JSON.stringify(value, null, 2).

Fix: Changed the error handler from using String(value) wrapped in custom styling to using JsonBlock(value), which is already used for similar complex attributes (metadata, input, output, eventData).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ Valid feedback, but instead of taking the diff, I'd just json-serialize the error

Copy link
Copy Markdown
Contributor Author

@pranaygp pranaygp Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would never get here if this was a structured error object though 🤔

structured error object are handled above and this is the string fallback for backwards compat no?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a structured error object or an Error instance, yes. I guess it's pretty impossible to have anything else in there, but I like the idea of being exhaustive when doing type checking. Maybe throw if we get to this code point and the value is an object. Also fine not to, it's a nit

pranaygp and others added 2 commits November 9, 2025 22:17
Comment thread workbench/nitro-v3/routes/api/trigger.get.ts
Comment thread packages/errors/src/index.ts
updatedAt: z.coerce.date(),
});

// Discriminated union based on status
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat

Comment thread packages/world/src/runs.ts Outdated
Comment thread packages/world-vercel/src/runs.ts Outdated
Comment on lines +125 to +139
return (
<DetailCard summary="Error">
<pre
className="text-copy-12 overflow-x-auto rounded-md border p-4"
style={{
borderColor: 'var(--ds-gray-300)',
backgroundColor: 'var(--ds-gray-100)',
color: 'var(--ds-gray-1000)',
whiteSpace: 'pre-wrap',
}}
>
<code>{String(value)}</code>
</pre>
</DetailCard>
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ Valid feedback, but instead of taking the diff, I'd just json-serialize the error

return (
<DetailCard summary="Error">
<pre
className="text-copy-12 overflow-x-auto rounded-md border p-4"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

De-dupe with styling above by extracting component

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I'll fix this in a follow up PR. the PR stack has gotten really messy with this git butler thing and everythings in a bad state so I just wanna get this merged in and fix the rest of your comments in a separate PR completely

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna merge this if the current tests pass and then open a fix PR directly on main with more stuff

<pre
className="text-copy-12 overflow-x-auto rounded-md border p-4"
style={{
borderColor: 'var(--ds-gray-300)',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not relevant to PR, but reminder to myself that I gotta fix these variable names to be tw classes

Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For old runs, I get this error for Web/CLI, which makes sense. It would be neat if this was backwards compatible, but I think it doesn't need to be.
image

@pranaygp
Copy link
Copy Markdown
Contributor Author

@VaguelySerious which world is that? The world code should be written in a way that's backwards compatible. Maybe I forgot to do its with local world though

@VaguelySerious
Copy link
Copy Markdown
Member

^ yeah local world

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter has a type mismatch where the returned promise type includes void but the declared type only expects Date | undefined, causing TypeScript compilation to fail.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..e25a98c 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt === undefined ? undefined : run.completedAt);
   }
 
   /**

Analysis

TypeScript type mismatch in workflow run completedAt getter

What fails: TypeScript compilation fails in packages/core/src/runtime.ts at line 161 due to type mismatch in the completedAt getter

How to reproduce:

pnpm turbo build --filter=@workflow/core

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter method has a type mismatch where the return type expects Promise<Date | undefined> but the actual return includes void instead of undefined due to the discriminated union in the WorkflowRun schema.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..879d884 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,10 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      const completedAt = run.completedAt as Date | void;
+      return completedAt === undefined ? undefined : completedAt;
+    });
   }
 
   /**

Analysis

TypeScript compilation error in runtime.ts completedAt getter

What fails: TypeScript compiler fails on packages/core/src/runtime.ts:161 due to type mismatch in the completedAt getter method

How to reproduce:

pnpm turbo build --filter="@workflow/core"

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter method returns a Promise that can contain void | Date | undefined but the method signature expects Promise<Date | undefined>. The discriminated union for WorkflowRun allows completedAt to be void for non-final workflow states, causing a TypeScript compilation error.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..b428ee2 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt || undefined);
   }
 
   /**

Analysis

TypeScript compilation failure in workflow core package

What fails: TypeScript compiler fails on packages/core/src/runtime.ts at line 161 due to type mismatch in the completedAt getter method

How to reproduce:

cd packages/core && pnpm run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter has a type mismatch because the Zod schema defines completedAt as void for non-final workflow states but Date for final states, creating a union type that doesn't match the expected Promise<Date | undefined> return type.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..8a0ea29 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,14 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      // For non-final states (pending, running, paused), completedAt is void
+      // For final states (cancelled, completed, failed), completedAt is Date
+      if (run.status === 'pending' || run.status === 'running' || run.status === 'paused') {
+        return undefined;
+      }
+      return run.completedAt as Date;
+    });
   }
 
   /**

Analysis

TypeScript compilation failure due to incompatible Promise return types

What fails: TypeScript compiler fails on packages/core/src/runtime.ts at line 161 due to incompatible Promise return types

How to reproduce:

cd packages/core && pnpm run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter returns a type that doesn't match its declared return type because the Zod schema defines completedAt as void for non-completed workflow runs, but the getter expects Date | undefined.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..390298a 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,10 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      // Handle the case where completedAt is void for non-completed runs
+      return run.completedAt instanceof Date ? run.completedAt : undefined;
+    });
   }
 
   /**

Analysis

TypeScript compilation failure due to type mismatch in WorkflowRun completedAt property

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to type incompatibility between the discriminated union schema and the getter return type

How to reproduce:

cd packages/core && pnpm run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.

Root cause: The WorkflowRun schema uses discriminated unions where completedAt can be void for non-completed workflow runs (pending/running/paused status) or Date for completed runs, but the completedAt getter expected only Date | undefined.

Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter returns a Promise that can include void type, but the method signature only allows Date | undefined. The issue occurs because the WorkflowRun schema defines completedAt as void for non-final states and Date for final states.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..b428ee2 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt || undefined);
   }
 
   /**

Analysis

TypeScript compilation error in runtime.ts completedAt getter

What fails: TypeScript compiler fails on src/runtime.ts(161,5) due to type mismatch in Promise return type

How to reproduce:

cd packages/core && pnpm run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter returns a Promise that includes void in its union type, but the method signature expects only Date | undefined. The discriminated union in WorkflowRun uses void for non-final states and Date for completed states, causing a TypeScript compilation error.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..b428ee2 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt || undefined);
   }
 
   /**

Analysis

TypeScript compilation failure in @workflow/core due to incompatible return type

What fails: TypeScript compilation fails on packages/core/src/runtime.ts at line 161 due to incompatible Promise return type

How to reproduce:

pnpm turbo run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter method returns Promise<void | Date | undefined> but is typed to return Promise<Date | undefined>. This occurs because the WorkflowRun discriminated union allows completedAt to be void for non-final workflow states, but the getter method doesn't handle this case.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..b428ee2 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt || undefined);
   }
 
   /**

Analysis

TypeScript compilation error in WorkflowRuntime.completedAt getter

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to type mismatch in completedAt getter method

How to reproduce:

turbo run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter method has a type mismatch where the return type is declared as Promise<Date | undefined> but the discriminated union WorkflowRun type includes void for non-final workflow states, causing TypeScript compilation to fail.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..8a0ea29 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,14 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      // For non-final states (pending, running, paused), completedAt is void
+      // For final states (cancelled, completed, failed), completedAt is Date
+      if (run.status === 'pending' || run.status === 'running' || run.status === 'paused') {
+        return undefined;
+      }
+      return run.completedAt as Date;
+    });
   }
 
   /**

Analysis

TypeScript compilation error in @workflow/core package

What fails: TypeScript compiler fails on packages/core/src/runtime.ts:161 due to return type mismatch in completedAt getter method

How to reproduce:

turbo run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter has a TypeScript compilation error because it returns Promise<void | Date | undefined> instead of the expected Promise<Date | undefined>. The discriminated union schema allows void values for non-final workflow states, but the getter's return type doesn't account for this.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..1164f23 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,10 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      const completedAt = run.completedAt;
+      return completedAt instanceof Date ? completedAt : undefined;
+    });
   }
 
   /**

Analysis

TypeScript compilation failure due to Promise return type mismatch

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to incompatible Promise return type in completedAt getter

How to reproduce:

npx turbo run build --filter=@workflow/core

Result:

@workflow/core:build: src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
@workflow/core:build:   Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
@workflow/core:build:     Type 'void' is not assignable to type 'Date | undefined'.

The completedAt getter was returning run.completedAt directly, but the discriminated union schema in packages/world/src/runs.ts defines completedAt: z.void() for non-final workflow states (pending, running, paused), causing the return type to include void.

Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter has a type mismatch where WorkflowRun.completedAt returns void | Date but the method signature expects Promise<Date | undefined>.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..b428ee2 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt || undefined);
   }
 
   /**

Analysis

TypeScript compilation failure in runtime.ts completedAt getter

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to type mismatch in the completedAt getter method

How to reproduce:

cd packages/core && pnpm build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.

Issue: The WorkflowRun.completedAt property can be void | Date based on the discriminated union schema, but the method signature expects Promise<Date | undefined>. The void type from non-final workflow states needs to be converted to undefined.

Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter method has a TypeScript type mismatch where the Zod discriminated union returns void | Date | undefined but the method signature expects Promise<Date | undefined>. The void type from non-final workflow states needs to be converted to undefined.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..b428ee2 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,7 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => run.completedAt || undefined);
   }
 
   /**

Analysis

TypeScript compilation error in completedAt getter

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to type mismatch in completedAt getter method

How to reproduce:

cd packages/core && pnpm run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter method has a type mismatch where the discriminated union type WorkflowRun.completedAt can be void | Date | undefined but the method signature expects only Promise<Date | undefined>. The void type from non-final workflow states is not assignable to Date | undefined.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..aaa772b 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,10 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      // For non-final states, completedAt is void; for final states, it's Date
+      return run.completedAt as Date | undefined;
+    });
   }
 
   /**

Analysis

TypeScript compilation failure due to discriminated union type mismatch

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to incompatible return type in completedAt getter

How to reproduce:

cd packages/core && pnpm build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

The completedAt getter returns Promise<void | Date | undefined> but is declared to return Promise<Date | undefined>. The void type from the discriminated union for non-final workflow states cannot be assigned to Date | undefined.

View Details
📝 Patch Details
diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts
index 069accb..7fe8de3 100644
--- a/packages/core/src/runtime.ts
+++ b/packages/core/src/runtime.ts
@@ -158,7 +158,9 @@ export class Run<TResult> {
    * Returns undefined if the workflow has not completed yet.
    */
   get completedAt(): Promise<Date | undefined> {
-    return this.world.runs.get(this.runId).then((run) => run.completedAt);
+    return this.world.runs.get(this.runId).then((run) => {
+      return run.completedAt instanceof Date ? run.completedAt : undefined;
+    });
   }
 
   /**

Analysis

TypeScript compilation error in runtime.ts

What fails: TypeScript compiler fails on packages/core/src/runtime.ts line 161 due to type mismatch in the completedAt getter

How to reproduce:

cd packages/core && pnpm run build

Result:

src/runtime.ts(161,5): error TS2322: Type 'Promise<void | Date | undefined>' is not assignable to type 'Promise<Date | undefined>'.
  Type 'void | Date | undefined' is not assignable to type 'Date | undefined'.
    Type 'void' is not assignable to type 'Date | undefined'.
Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants