R2 · SDK bug report — Promise.all + ctx.task journal collision
Title
Promise.all + multiple ctx.task emissions cause duplicate effects with collided journal sequence numbers
Summary
When a process function calls ctx.task from inside multiple Promise.all branches simultaneously, the babysitter SDK assigns the same stepId (and same journal sequence number) to two different effects. The journal ends up with two entries at the same seq; the state cache cannot reconcile; iterations stall or emit ghost effects.
Reproduction
Minimal process file:
import { defineTask } from '@a5c-ai/babysitter-sdk';
export const taskA = defineTask('parallel-a', () => ({ kind: 'agent', title: 'A' }));
export const taskB = defineTask('parallel-b', () => ({ kind: 'agent', title: 'B' }));
export const taskC = defineTask('parallel-c', () => ({ kind: 'agent', title: 'C' }));
export async function process(_inputs, ctx) {
const [a, b, c] = await Promise.all([
ctx.task(taskA, {}),
ctx.task(taskB, {}),
ctx.task(taskC, {}),
]);
return { a, b, c };
}
Run with babysitter run:create ... && babysitter run:iterate .... Examine the journal — at least two events at the same seq.
Concrete evidence (from a real run)
In cookbook run 01KT797KHQ6RFVMJ55TPBQ1K26 (V2 lane epic, 2026-06-03):
- Journal seq 4 had TWO entries:
000004.01KT798JNFRF4GCVFBBN0531TC.json (Lane B mockup task) and 000004.01KT798JNFRF4GCVFBBN0531TD.json (was Lane A's impl task)
babysitter run:iterate returned the error Journal sequence gap detected at 000004.01KT798JNFRF4GCVFBBN0531TD.json (expected 5, got 4)
- Recovery required manually deleting one of the duplicate-seq files
The issue is that step IDs (S000003, S000004, etc.) appear to be assigned by Promise.all interleaving order, but the journal sequence numbers (000001, 000002, ...) collide because emission order is non-deterministic at sub-ms granularity.
Suggested fix direction
StepIds should derive from the invocation key (process file path + task name + cumulative invocation count for that task), not from monotonic emission order. Same for journal sequence numbers — they should advance once per persisted event, with deterministic ordering even when emission is concurrent.
OR: Document that Promise.all + ctx.task is unsupported, and recommend sequential for...of loops.
Environment
- @a5c-ai/babysitter-sdk: (current version on cookbook, 2026-06-03)
- Node 24
- macOS / Claude Code harness
R2 · SDK bug report — Promise.all + ctx.task journal collision
Title
Promise.all + multiple ctx.task emissions cause duplicate effects with collided journal sequence numbersSummary
When a process function calls
ctx.taskfrom inside multiplePromise.allbranches simultaneously, the babysitter SDK assigns the samestepId(and same journal sequence number) to two different effects. The journal ends up with two entries at the sameseq; the state cache cannot reconcile; iterations stall or emit ghost effects.Reproduction
Minimal process file:
Run with
babysitter run:create ... && babysitter run:iterate .... Examine the journal — at least two events at the same seq.Concrete evidence (from a real run)
In cookbook run
01KT797KHQ6RFVMJ55TPBQ1K26(V2 lane epic, 2026-06-03):000004.01KT798JNFRF4GCVFBBN0531TC.json(Lane B mockup task) and000004.01KT798JNFRF4GCVFBBN0531TD.json(was Lane A's impl task)babysitter run:iteratereturned the errorJournal sequence gap detected at 000004.01KT798JNFRF4GCVFBBN0531TD.json (expected 5, got 4)The issue is that step IDs (S000003, S000004, etc.) appear to be assigned by Promise.all interleaving order, but the journal sequence numbers (000001, 000002, ...) collide because emission order is non-deterministic at sub-ms granularity.
Suggested fix direction
StepIds should derive from the invocation key (process file path + task name + cumulative invocation count for that task), not from monotonic emission order. Same for journal sequence numbers — they should advance once per persisted event, with deterministic ordering even when emission is concurrent.
OR: Document that Promise.all + ctx.task is unsupported, and recommend sequential
for...ofloops.Environment