can1357/oh-my-pi · error · ToolError
Vibe sessions require a stable parent session id.
Error message
Vibe sessions require a stable parent session id.
What it means
The Vibe runtime scopes every worker record to a parent session (ownerId + parentSessionId + parentSessionFile). ownerScope() computes that scope from the parent session object, and throws when session.getSessionId?.() returns nothing. Without a stable parent session id the registry could not key records, persist lifecycle tombstones, or verify that the parent session has not changed between operations.
Source
Thrown at packages/coding-agent/src/vibe/runtime.ts:364
suspended: false,
terminalPersisted: false,
});
}
readonly #records = new Map<string, VibeRecord>();
readonly #terminationTails = new Map<string, Promise<void>>();
readonly #terminatedScopes = new Set<string>();
#teardownGraceMs = VIBE_TEARDOWN_GRACE_MS;
/** Override the teardown grace period for deterministic lifecycle tests. */
setTeardownGraceForTesting(timeoutMs: number): void {
this.#teardownGraceMs = Math.max(1, timeoutMs);
}
ownerScope(session: VibeParentSession): VibeOwnerScope {
const parentSessionId = session.getSessionId?.();
if (!parentSessionId) {
throw new ToolError("Vibe sessions require a stable parent session id.");
}
const parentSessionFile = session.getSessionFile();
return {
ownerId: session.getAgentId?.() ?? MAIN_AGENT_ID,
parentSessionId,
parentSessionFile: parentSessionFile ? path.resolve(parentSessionFile) : null,
};
}
/** Re-open spawn admission after an explicit Vibe-mode entry. */
activateScope(scope: VibeOwnerScope): void {
this.#terminatedScopes.delete(scopeKey(scope, ""));
}
async #withTerminationLock<T>(scope: VibeOwnerScope, operation: () => Promise<T>): Promise<T> {
const key = scopeKey(scope, "");
const predecessor = this.#terminationTails.get(key) ?? Promise.resolve();
const released = Promise.withResolvers<void>();View on GitHub (pinned to 9690622007)
Solutions
- Ensure the VibeParentSession implementation's getSessionId() returns a non-empty stable id before invoking any vibe operation.
- If constructing a session manually (SDK/test), assign a durable id (e.g. UUID persisted with the session file) at construction time.
- Fix lazy initialization so getSessionId() is never consulted before the id is set, or make ownerScope callers wait for initialization.
Example fix
// before
const registry = VibeSessionRegistry.global();
registry.scope(sessionWithoutId as VibeParentSession); // throws
// after
const session = sessionWithoutId as VibeParentSession;
if (!session.getSessionId?.()) session.initialize({ id: crypto.randomUUID() });
registry.scope(session); Defensive patterns
Strategy: validation
Validate before calling
const id = session.getSessionId?.();
if (!id) throw new Error("Parent session must have a stable id before vibe operations"); Type guard
function hasStableSessionId(s: VibeParentSession): s is VibeParentSession & { getSessionId: () => string } {
return typeof s.getSessionId === "function" && !!s.getSessionId();
} Try / catch
try {
registry.ownerScope(session);
} catch (err) {
if (err instanceof ToolError && err.message.includes("stable parent session id")) {
session.initialize({ id: crypto.randomUUID() });
} else throw err;
} Prevention
- Assign a durable session id at session construction, never lazily
- Type-check VibeParentSession implementations so getSessionId is non-optional
- Unit-test custom session doubles with ownerScope before using them in vibe flows
When it happens
Trigger: Calling ownerScope() (directly or via currentScope/listIds/scope, and transitively via spawn/kill/persistModeExit) with a VibeParentSession whose getSessionId() is undefined or returns an empty string — e.g. a stub session or a session constructed before its id was assigned.
Common situations: Embedding the SDK and passing a hand-rolled VibeParentSession that omits getSessionId; building a synthetic session in tests without an id; a session implementation whose id is set lazily and read before initialization.
Related errors
- No session - local:// unavailable
- options.authStorage and options.modelRegistry.authStorage mu
- Vibe tools are unavailable in this session.
- Vibe sessions require async execution (no background job man
- No active model on agent
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/39554959c539258f.
Report an issue: GitHub.