@@ -571,29 +571,27 @@ describe('e2e', () => {
571571 expect ( returnValue ) . toHaveProperty ( 'cause' ) ;
572572 expect ( returnValue . cause ) . toBeTypeOf ( 'object' ) ;
573573 expect ( returnValue . cause ) . toHaveProperty ( 'message' ) ;
574- expect ( returnValue . cause . message ) . toContain (
575- 'Error from imported helper module'
576- ) ;
574+ expect ( returnValue . cause . message ) . toContain ( 'Error from workflow helper' ) ;
577575
578576 // Verify the stack trace is present in the cause
579577 expect ( returnValue . cause ) . toHaveProperty ( 'stack' ) ;
580578 expect ( typeof returnValue . cause . stack ) . toBe ( 'string' ) ;
581579
582580 // Known issue: SvelteKit dev mode has incorrect source map mappings for bundled imports.
583- // esbuild with bundle:true inlines helpers.ts but source maps incorrectly map to 99_e2e.ts
581+ // esbuild with bundle:true inlines the helper but source maps incorrectly map to 99_e2e.ts
584582 // This works correctly in production and other frameworks.
585583 // TODO: Investigate esbuild source map generation for bundled modules
586584 const isSvelteKitDevMode =
587585 process . env . APP_NAME === 'sveltekit' && isLocalDeployment ( ) ;
588586
589587 if ( ! isSvelteKitDevMode ) {
590- // Stack trace should include frames from the helper module (helpers.ts)
591- expect ( returnValue . cause . stack ) . toContain ( 'helpers .ts' ) ;
588+ // Stack trace should include frames from the workflow error test module
589+ expect ( returnValue . cause . stack ) . toContain ( '98_workflow_error_test .ts' ) ;
592590 }
593591
594592 // These checks should work in all modes
595- expect ( returnValue . cause . stack ) . toContain ( 'throwError ' ) ;
596- expect ( returnValue . cause . stack ) . toContain ( 'callThrower ' ) ;
593+ expect ( returnValue . cause . stack ) . toContain ( 'throwWorkflowError ' ) ;
594+ expect ( returnValue . cause . stack ) . toContain ( 'workflowErrorHelper ' ) ;
597595
598596 // Stack trace should include frames from the workflow file (99_e2e.ts)
599597 expect ( returnValue . cause . stack ) . toContain ( '99_e2e.ts' ) ;
@@ -606,9 +604,83 @@ describe('e2e', () => {
606604 const { json : runData } = await cliInspectJson ( `runs ${ run . runId } ` ) ;
607605 expect ( runData . status ) . toBe ( 'failed' ) ;
608606 expect ( runData . error ) . toBeTypeOf ( 'object' ) ;
609- expect ( runData . error . message ) . toContain (
610- 'Error from imported helper module'
607+ expect ( runData . error . message ) . toContain ( 'Error from workflow helper' ) ;
608+ }
609+ ) ;
610+
611+ test (
612+ 'deepStepErrorWorkflow - stack traces work with step errors across multiple files' ,
613+ { timeout : 60_000 } ,
614+ async ( ) => {
615+ // This workflow intentionally throws a FatalError from a step that calls imported helpers
616+ // Call chain: deepStepErrorWorkflow -> deepStepWithNestedError (step) -> stepErrorHelper -> throwStepError
617+ // This verifies that stack traces preserve the call chain from step errors
618+ const run = await triggerWorkflow ( 'deepStepErrorWorkflow' , [ ] ) ;
619+ const returnValue = await getWorkflowReturnValue ( run . runId ) ;
620+
621+ // The workflow should fail with error response
622+ expect ( returnValue ) . toHaveProperty ( 'name' ) ;
623+ expect ( returnValue . name ) . toBe ( 'WorkflowRunFailedError' ) ;
624+ expect ( returnValue ) . toHaveProperty ( 'message' ) ;
625+
626+ // Verify the cause property contains the structured error
627+ expect ( returnValue ) . toHaveProperty ( 'cause' ) ;
628+ expect ( returnValue . cause ) . toBeTypeOf ( 'object' ) ;
629+ expect ( returnValue . cause ) . toHaveProperty ( 'message' ) ;
630+ expect ( returnValue . cause . message ) . toContain ( 'Error from step helper' ) ;
631+
632+ // Verify the stack trace contains the error chain
633+ expect ( returnValue . cause ) . toHaveProperty ( 'stack' ) ;
634+ expect ( typeof returnValue . cause . stack ) . toBe ( 'string' ) ;
635+
636+ // Log the full stack trace for debugging
637+ console . log ( 'Full stack trace from deepStepErrorWorkflow:' ) ;
638+ console . log ( returnValue . cause . stack ) ;
639+
640+ // Known issue: SvelteKit dev mode has incorrect source map mappings for bundled imports.
641+ const isSvelteKitDevMode =
642+ process . env . APP_NAME === 'sveltekit' && isLocalDeployment ( ) ;
643+
644+ if ( ! isSvelteKitDevMode ) {
645+ // Stack trace should include frames from the step error test module
646+ expect ( returnValue . cause . stack ) . toContain ( '98_step_error_test.ts' ) ;
647+ }
648+
649+ // These checks should work in all modes - verify the call chain
650+ // Bottom of stack: the error thrower
651+ expect ( returnValue . cause . stack ) . toContain ( 'throwStepError' ) ;
652+
653+ // Middle layer: helper function
654+ expect ( returnValue . cause . stack ) . toContain ( 'stepErrorHelper' ) ;
655+
656+ // Top layer: the step function
657+ expect ( returnValue . cause . stack ) . toContain ( 'deepStepWithNestedError' ) ;
658+
659+ // Note: Workflow functions don't appear in the step error's stack trace
660+ // because they execute in the workflow VM context, while the error
661+ // originates in the step execution Node.js context. This is expected.
662+
663+ // Stack trace should NOT contain 'evalmachine' anywhere
664+ expect ( returnValue . cause . stack ) . not . toContain ( 'evalmachine' ) ;
665+
666+ // Verify the run failed with structured error
667+ const { json : runData } = await cliInspectJson ( `runs ${ run . runId } ` ) ;
668+ expect ( runData . status ) . toBe ( 'failed' ) ;
669+ expect ( runData . error ) . toBeTypeOf ( 'object' ) ;
670+ expect ( runData . error . message ) . toContain ( 'Error from step helper' ) ;
671+
672+ // Verify it was a step execution failure (not a workflow execution failure)
673+ // The error should come from a step, so check the steps
674+ const { json : stepsData } = await cliInspectJson (
675+ `steps --runId ${ run . runId } `
611676 ) ;
677+ expect ( Array . isArray ( stepsData ) ) . toBe ( true ) ;
678+ expect ( stepsData . length ) . toBeGreaterThan ( 0 ) ;
679+
680+ // Find the failed step
681+ const failedStep = stepsData . find ( ( s : any ) => s . status === 'failed' ) ;
682+ expect ( failedStep ) . toBeDefined ( ) ;
683+ expect ( failedStep . stepName ) . toContain ( 'deepStepWithNestedError' ) ;
612684 }
613685 ) ;
614686} ) ;
0 commit comments