@@ -10,8 +10,8 @@ import {
1010 type WorkflowErrorEvent ,
1111 type WorkflowContextInterface ,
1212} from "../src/testing.js" ;
13- import { buildHistoryPrefixAll , keyStartsWith } from "../src/keys.js" ;
14- import { deserializeEntry , serializeEntry } from "../schemas/serde.js" ;
13+ import { buildHistoryPrefixAll } from "../src/keys.js" ;
14+ import { deserializeEntry } from "../schemas/serde.js" ;
1515
1616const modes = [ "yield" , "live" ] as const ;
1717
@@ -26,30 +26,6 @@ class CountingDriver extends InMemoryDriver {
2626 }
2727}
2828
29- class StripStepHistoryErrorDriver extends InMemoryDriver {
30- override async batch (
31- writes : { key : Uint8Array ; value : Uint8Array } [ ] ,
32- ) : Promise < void > {
33- const historyPrefix = buildHistoryPrefixAll ( ) ;
34- const rewritten = writes . map ( ( write ) => {
35- if ( ! keyStartsWith ( write . key , historyPrefix ) ) {
36- return write ;
37- }
38-
39- const entry = deserializeEntry ( write . value ) ;
40- if ( entry . kind . type === "step" ) {
41- // Simulate a driver/crash scenario where the step error is not persisted
42- // to the history entry, even though retries/exhaustion metadata is.
43- entry . kind . data . error = undefined ;
44- return { key : write . key , value : serializeEntry ( entry ) } ;
45- }
46-
47- return write ;
48- } ) ;
49-
50- return await super . batch ( rewritten ) ;
51- }
52- }
5329
5430for ( const mode of modes ) {
5531 describe ( `Workflow Engine Steps (${ mode } )` , { sequential : true } , ( ) => {
@@ -485,43 +461,6 @@ for (const mode of modes) {
485461 ) . rejects . toThrow ( StepExhaustedError ) ;
486462 } ) ;
487463
488- it ( "should surface the last error even if step history is missing the error" , async ( ) => {
489- const driver = new StripStepHistoryErrorDriver ( ) ;
490- driver . latency = 0 ;
491-
492- const workflow = async ( ctx : WorkflowContextInterface ) => {
493- return await ctx . step ( {
494- name : "always-fails" ,
495- maxRetries : 1 ,
496- retryBackoffBase : 0 ,
497- retryBackoffMax : 0 ,
498- run : async ( ) => {
499- throw new Error ( "Always fails" ) ;
500- } ,
501- } ) ;
502- } ;
503-
504- if ( mode === "yield" ) {
505- const firstResult = await runWorkflow (
506- "wf-1" ,
507- workflow ,
508- undefined ,
509- driver ,
510- { mode } ,
511- ) . result ;
512- expect ( firstResult . state ) . toBe ( "sleeping" ) ;
513- }
514-
515- await expect (
516- runWorkflow ( "wf-1" , workflow , undefined , driver , { mode } )
517- . result ,
518- ) . rejects . toThrow ( StepExhaustedError ) ;
519- await expect (
520- runWorkflow ( "wf-1" , workflow , undefined , driver , { mode } )
521- . result ,
522- ) . rejects . toThrow ( / A l w a y s f a i l s / ) ;
523- } ) ;
524-
525464 it ( "should recover exhausted retries" , async ( ) => {
526465 let attempts = 0 ;
527466
@@ -634,5 +573,40 @@ for (const mode of modes) {
634573 expect ( result . output ) . toBe ( "done" ) ;
635574 expect ( driver . batchCalls ) . toBe ( 2 ) ;
636575 } ) ;
576+
577+ it ( "should not commit step error data to entry on failure" , async ( ) => {
578+ const workflow = async ( ctx : WorkflowContextInterface ) => {
579+ return await ctx . step ( {
580+ name : "fail-once" ,
581+ maxRetries : 3 ,
582+ retryBackoffBase : 0 ,
583+ retryBackoffMax : 0 ,
584+ run : async ( ) => {
585+ throw new Error ( "step failed" ) ;
586+ } ,
587+ } ) ;
588+ } ;
589+
590+ // Run once so the step fails and state is flushed
591+ try {
592+ await runWorkflow ( "wf-1" , workflow , undefined , driver , {
593+ mode,
594+ } ) . result ;
595+ } catch { }
596+
597+ // Inspect all history entries in KV
598+ const historyPrefix = buildHistoryPrefixAll ( ) ;
599+ const entries = await driver . list ( historyPrefix ) ;
600+
601+ for ( const kv of entries ) {
602+ const entry = deserializeEntry ( kv . value ) ;
603+ if ( entry . kind . type === "step" ) {
604+ // The step entry should have no output committed on failure.
605+ expect ( entry . kind . data . output ) . toBeUndefined ( ) ;
606+ // The error should be committed for inspection.
607+ expect ( entry . kind . data . error ) . toBe ( "Error: step failed" ) ;
608+ }
609+ }
610+ } ) ;
637611 } ) ;
638612}
0 commit comments