Skip to content

feat(ocap-kernel): name the failing vat when a subcluster vat fails to launch#975

Draft
grypez wants to merge 7 commits into
mainfrom
grypez/issue-572-launchvats-throw-repro
Draft

feat(ocap-kernel): name the failing vat when a subcluster vat fails to launch#975
grypez wants to merge 7 commits into
mainfrom
grypez/issue-572-launchvats-throw-repro

Conversation

@grypez

@grypez grypez commented Jul 14, 2026

Copy link
Copy Markdown
Member

Closes #564
Closes #572

Explanation

When a vat in a subcluster fails to launch — most notably when its buildRootObject throws, surfacing from VatHandle.make as Failed to initialize vat <vatId>: ... — the error previously propagated through #launchVatsForSubcluster verbatim, giving no indication of which ClusterConfig vat failed (the internal kernel id alone is meaningless to someone reading a cluster config).

VatManager.launchVat now wraps runVat and, on failure, re-throws attributing the failure to the specific vat by both its kernel id and its ClusterConfig name, preserving the original error as the cause:

Failed to launch vat v3 (bob)

This is the only seam where both the minted vatId and the vatName are in scope. SubclusterManager.launchSubcluster already rolls back the subcluster and rethrows on the failure, so the named error surfaces to the caller.

This addresses the "throw an error describing which vats failed to buildRootObject" ask from #564. It also confirms (via new regression tests) that the original cryptic symptom — SES_UNHANDLED_REJECTION: no record matching key 'queue.run.3' (#572) — no longer occurs: the bootstrap subroutines reject cleanly and roll back.

Changes

  • VatManager.launchVat: attribute launch failures to <vatId> (<vatName>), with the original error as cause; omit the parenthetical when launched without a name.
  • Tests: VatManager.test.ts covers the attribution, cause preservation, and no-name cases. SubclusterManager.test.ts adds #572 regression tests for clean bootstrap-failure propagation and rollback.

References

Checklist

  • I've clearly explained what changes were made and why.
  • I've added tests to cover my changes.
  • I've applied the appropriate labels (breaking / non-breaking).
  • I've communicated my changes in the changelog.

🤖 Generated with Claude Code

grypez and others added 4 commits July 14, 2026 13:04
…o launch

When a vat fails to launch (e.g. its `buildRootObject` throws, surfacing
from `VatHandle.make`), `VatManager.launchVat` now re-throws attributing
the failure to the specific vat by both its kernel id and its
`ClusterConfig` name, e.g. `Failed to launch vat v3 (bob)`, preserving the
original error as the cause. Previously the underlying error propagated
verbatim with no indication of which subcluster vat failed.

Also adds regression tests for #572 covering clean bootstrap-failure
propagation and rollback in `SubclusterManager`.

Refs: #564, #572

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Refs: #564, #572

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A failed vat launch is now re-thrown by `VatManager.launchVat` as
`Failed to launch vat <id> (<name>)` with the original error preserved on
`cause`. Update the integration assertions that previously matched the
detail (excluded global, `buildRootObject`/global-scope throw) in the
top-level message to search the `cause` chain instead, via a shared
`causeChainMessage` helper. The bootstrap-throw path is unchanged (it does
not flow through `launchVat`).

Refs: #564, #572

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A vat launch that fails at the `initVat` RPC boundary (e.g. an excluded
global, invalid params) surfaces as a plain JSON-RPC error object
(`{ code, message, data }`) rather than an `Error`, which `VatManager.launchVat`
then preserves on `cause`. The previous helper gated its walk on
`instanceof Error`, so it stopped at such a cause and lost the detail.
Walk anything with a `message`/`cause` and fold in `data`, so the
launch-failure assertions find the reason regardless of the cause's shape.
Add direct unit coverage for the helper.

Refs: #564, #572

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 71.4%
⬆️ +0.01%
8874 / 12427
🔵 Statements 71.23%
⬆️ +0.02%
9024 / 12668
🔵 Functions 72.59%
🟰 ±0%
2140 / 2948
🔵 Branches 64.95%
⬆️ +0.03%
3588 / 5524
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/ocap-kernel/src/vats/VatManager.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
Generated in workflow #4533 for commit d977b8b by the Vitest Coverage Report Action

grypez and others added 3 commits July 15, 2026 11:44
…e helper

Assert launch failures with `toMatchObject`: the top-level message is the
`Failed to launch vat <id> (<name>)` attribution wrapper and the reason lives
on `cause.message`. `toMatchObject` matches both a real `Error` cause (the
delivery-error path) and a plain JSON-RPC error object (the initVat RPC
boundary), so the `causeChainMessage` helper and its unit test are no longer
needed and are removed.

Refs: #564, #572

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the catch-and-store pattern and assert directly on the rejected promise
via `rejects.toMatchObject`, matching the `Failed to launch vat <id> (<name>)`
attribution message and the reason on `cause.message`.

Refs: #564, #572

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant