Skip to content

fix(selfhost): gate the queue consumer on env readiness at boot - #5050

Merged
JSONbored merged 1 commit into
mainfrom
fix/selfhost-consume-env-boot-race
Jul 11, 2026
Merged

fix(selfhost): gate the queue consumer on env readiness at boot#5050
JSONbored merged 1 commit into
mainfrom
fix/selfhost-consume-env-boot-race

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • The self-host queue consumer closure (consume in src/server.ts) captures env, which isn't assigned until ~250 lines / several awaited boot steps after the queue backend is constructed.
  • Both queue backends deliberately self-heal any foreground-priority job left over-deferred across a restart by calling releaseStaleForegroundDeferrals() once at boot (in addition to its normal periodic sweep), which can call kickAll() -> consume(message) -> processJob(env, ...) before env is set, dereferencing undefined.
  • Surfaces as a misleading generic job_error audit event (TypeError: Cannot read properties of undefined) right after a container restart, only when a foreground job happened to be sitting deferred and release-eligible at that exact moment — self-heals on the very next retry, masking the real cause.
  • Fix: consume now awaits an envReady promise, resolved immediately after env is fully assigned, so an early release just waits instead of dereferencing env early. Confined entirely to server.ts, which is shared by both queue backends — no changes needed in pg-queue.ts/sqlite-queue.ts.

Closes #5049

Test plan

  • npm run typecheck — clean
  • npm run test:coverage (full, unsharded) — 717 files / 14146 tests passed, 0 failures
  • npm run test:ci (full gate, incl. UI lint/typecheck/test/build, migrations/schema-drift/openapi/docs-drift checks) — green
  • npm audit --audit-level=moderate — 0 vulnerabilities
  • src/server.ts is in codecov.yml's ignore list (self-host process entry; validated by the Docker boot smoke test in .github/workflows/selfhost.yml, not unit-coverable without booting a real server/subprocess) — no dedicated unit test added for this exact race, consistent with how the rest of that file is handled.

Both queue backends self-heal a foreground job left over-deferred
across a restart by releasing it and kicking the pump once at boot,
inside queue construction/init() itself. That can invoke consume()
before `env` is assigned further down in main(), dereferencing
undefined and surfacing as a misleading generic job_error right after
a container restart. consume() now awaits an envReady promise resolved
once env is fully assigned.

Closes #5049
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.16%. Comparing base (8f10e83) to head (c0b1e1b).
⚠️ Report is 4 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5050   +/-   ##
=======================================
  Coverage   94.16%   94.16%           
=======================================
  Files         463      463           
  Lines       39429    39429           
  Branches    14384    14384           
=======================================
  Hits        37128    37128           
  Misses       1646     1646           
  Partials      655      655           
Flag Coverage Δ
shard-1 46.59% <ø> (-0.02%) ⬇️
shard-2 33.21% <ø> (-0.12%) ⬇️
shard-3 31.22% <ø> (-0.19%) ⬇️
shard-4 32.48% <ø> (-0.27%) ⬇️
shard-5 34.37% <ø> (+0.93%) ⬆️
shard-6 45.22% <ø> (+0.21%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored JSONbored self-assigned this Jul 11, 2026
@JSONbored
JSONbored merged commit 0943bb3 into main Jul 11, 2026
18 checks passed
@JSONbored
JSONbored deleted the fix/selfhost-consume-env-boot-race branch July 11, 2026 10: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.

Self-host: consume() can dereference undefined env during boot's foreground-liveness self-heal, surfacing as a misleading job_error

1 participant