Skip to content

fix(workflows): omit undefined step config keys from bridge - #1416

Merged
sam-goodwin merged 1 commit into
alchemy-run:mainfrom
LordCoughmann:fix/workflow-step-config-undefined-timeout
Aug 31, 2026
Merged

fix(workflows): omit undefined step config keys from bridge#1416
sam-goodwin merged 1 commit into
alchemy-run:mainfrom
LordCoughmann:fix/workflow-step-config-undefined-timeout

Conversation

@LordCoughmann

Copy link
Copy Markdown
Contributor

Problem

A Cloudflare.Workflows.task step that declares retries but no timeout crashes on the first attempt with:

TypeError: Cannot read properties of undefined (reading 'match')

Root cause

WorkflowBridge.toWorkflowStepConfig reconstructs the config object before handing it to the native step.do:

return { retries: options.retries, timeout: options.timeout };

When only retries is set, this produces { retries: {...}, timeout: undefined } — an explicitly present undefined key.

The local engine then merges step config over its defaults with a shallow spread:

let config: ResolvedStepConfig = { ...defaultConfig, ...stepConfig, retries: {...} };

so the explicit timeout: undefined overwrites defaultConfig.timeout ("10 minutes"). The step's timeout watchdog subsequently calls ms(config.timeout), and ms(undefined) throws the reading 'match' error inside itty-time.

Native cloudflare:workers callers never emit timeout: undefined (the key is simply absent), so this is specific to the Alchemy bridge.

Fix

Omit keys that are undefined in toWorkflowStepConfig, so a retries-only step keeps the engine timeout default:

const config: WorkflowStepConfig = {};
if (options.retries) config.retries = options.retries;
if (options.timeout !== undefined) config.timeout = options.timeout;
return Object.keys(config).length > 0 ? config : undefined;

Test

Adds a regression test in WorkflowBridge.test.ts asserting the bridge passes { retries } with no timeout key.

Notes

  • I could not run alchemy-test locally (existing test files fail with describe/test/hook called outside of a test file collection in my environment), so CI verification is appreciated.
  • Optional hardening (separate concern, not included): the engine's default-merge could defensively skip undefined values, which would make the engine resilient regardless of what the bridge passes.

The bridge reconstructed step config as `{ retries, timeout: undefined }`
when only retries was set. The engine merges config over its defaults with
a shallow spread, so the explicit undefined timeout overwrote the built-in
default and the timeout watchdog later crashed calling ms(undefined)
(TypeError: Cannot read properties of undefined (reading 'match')).

Omit keys that are undefined so a retries-only step keeps the engine
timeout default.
@sam-goodwin
sam-goodwin marked this pull request as ready for review August 31, 2026 19:47
@sam-goodwin

Copy link
Copy Markdown
Contributor

I ran the tests, they pass

@sam-goodwin
sam-goodwin merged commit 034c028 into alchemy-run:main Aug 31, 2026
5 checks passed
@LordCoughmann
LordCoughmann deleted the fix/workflow-step-config-undefined-timeout branch September 1, 2026 03:53
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.

2 participants