fix(ocap-kernel): quarantine unrestorable vats on kernel boot#977
Open
grypez wants to merge 2 commits into
Open
fix(ocap-kernel): quarantine unrestorable vats on kernel boot#977grypez wants to merge 2 commits into
grypez wants to merge 2 commits into
Conversation
grypez
added a commit
that referenced
this pull request
Jul 15, 2026
#977) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||
grypez
force-pushed
the
grypez/issue-964-restore-missing-bundle
branch
from
July 15, 2026 16:48
01d3c8f to
78f951d
Compare
grypez
force-pushed
the
grypez/issue-964-restore-missing-bundle
branch
from
July 15, 2026 19:02
78f951d to
21b3816
Compare
#964) Failing tests for VatManager.initializeAllVats: when a single persisted vat's launch rejects (e.g. its bundle is gone), the current Promise.all aborts the entire restore instead of quarantining the unrestorable vat and restoring the rest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
VatManager.initializeAllVats now restores each persisted vat in isolation. A vat whose bundle is missing or unresolvable (fetch rejects with e.g. ENOENT) is quarantined — skipped with a structured warning naming the vat, its subcluster, and its bundle — and the rest of the kernel boots. The persisted record is retained, so the vat is restored automatically on a later boot if its bundle returns. Previously one orphaned bundle reference made the whole kernel unbootable. Daemon-side observability of fatal exits (rendering the real error to daemon.log under `stdio: 'ignore'`) is handled separately by #966. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
grypez
force-pushed
the
grypez/issue-964-restore-missing-bundle
branch
from
July 16, 2026 14:53
21b3816 to
d65f902
Compare
grypez
marked this pull request as ready for review
July 16, 2026 15:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
On startup the daemon replays persisted subclusters and restarts their vats, fetching each vat's code from the
bundleSpecrecorded in the kernel store (the #963 restore path). If a single referenced bundle no longer exists on disk (moved, deleted, or otherwise unresolvable), the fetch throwsENOENT. BecauseVatManager.initializeAllVatsrestored every vat inside onePromise.all, that single rejection aborted the entire kernel boot — one orphaned bundle reference made the whole kernel unbootable.This PR makes restore fault-tolerant.
VatManager.initializeAllVatsnow restores each persisted vat in isolation. A vat whose launch rejects is quarantined — skipped, with a structured warning naming the vat, its subcluster, and its bundle spec — and the rest of the kernel boots normally. The persisted record is retained, so the vat is restored automatically on a later boot if its bundle returns (no silent deletion of persisted state).Scope
The linked issue (#964) also called for making the daemon's fatal exit observable (the real error, rendered to
daemon.log, instead of[object Object]on a discarded stderr). That observability work landed separately in #966, which installs file-scoped fatal handlers indaemon-entry.ts. This PR contains only the@metamask/ocap-kernelcorrectness fix and is rebased onmain(now including #966).With this fix, a missing bundle no longer aborts
makeKernel, so the daemon reaches its normal init path and boots successfully rather than leaving a wedged process.Test plan
VatManager.test.tscases: a persisted vat whose launch rejects is quarantined, the healthy vats still restore, and a structured warning naming the vat / subcluster / bundle is logged.@metamask/ocap-kernelsuite passes, including the existing fix(ocap-kernel): restore IO channels for persisted subclusters #963SubclusterManagertests.Closes #964
🤖 Generated with Claude Code
Note
Medium Risk
Touches the kernel startup path in
VatManager.initializeAllVats, but only adds per-vat error isolation on restore; explicit vat launch still fails fast.Overview
Kernel boot no longer fails when one persisted vat cannot be restored (e.g. missing
bundleSpec/ENOENT).VatManager.initializeAllVatsnow restores each vat through private#restoreVat, which catches launch failures, logs a structured warning (vat id, subcluster, source via newdescribeVatSource), and skips that vat while other restores still complete.Persisted vat records are not removed on quarantine, so a vat can come back on a later boot if its bundle is available again.
launchVat/runVatbehavior for explicit launches is unchanged—only the bulk restore path is fault-tolerant.Tests cover mixed healthy/unhealthy restores and warning content; CHANGELOG documents the fix.
Reviewed by Cursor Bugbot for commit d65f902. Bugbot is set up for automated code reviews on this repo. Configure here.