slopus/happy · error · Error
Resume session handler not available
Error message
Resume session handler not available
What it means
Thrown by the resume-session RPC handler when this.resumeSessionHandler is unset at the time the RPC arrives, even though a handler was registered. This is a narrow race/lifecycle window: the RPC method is registered but the actual callback has not been attached (or was detached), so the request cannot be fulfilled.
Source
Thrown at packages/happy-cli/src/api/apiMachine.ts:348
return { message: 'Daemon stop request acknowledged, starting shutdown sequence...' };
});
}
private syncResumeSessionRpcRegistration(): void {
const method = 'resume-happy-session';
if (this.resumeSessionHandler) {
if (!this.rpcHandlerManager.hasHandler(method)) {
this.rpcHandlerManager.registerHandler(method, async (params: any) => {
const { sessionId, model, permissionMode } = params || {};
if (!sessionId || typeof sessionId !== 'string') {
throw new Error('Session ID is required');
}
const handler = this.resumeSessionHandler;
if (!handler) {
throw new Error('Resume session handler not available');
}
const result = await handler(sessionId, { model, permissionMode });
switch (result.type) {
case 'success':
return { type: 'success', sessionId: result.sessionId };
case 'requestToApproveDirectoryCreation':
return result;
case 'error':
throw new Error(result.errorMessage);
}
});
}
return;
}
if (this.rpcHandlerManager.hasHandler(method)) {
this.rpcHandlerManager.unregisterHandler(method);View on GitHub (pinned to b824cd0a46)
Solutions
- Wait for the client connection/initialization to complete before calling resume-session
- Retry the RPC after a short delay so the handler is attached
- Ensure setRPCHandlers/connect assigns resumeSessionHandler before (or atomically with) registering the RPC method
Example fix
// before
await connect();
await rpc.call('session/resume', { sessionId }); // may race
// after
await connect();
await waitFor(client.ready); // handler attached
await rpc.call('session/resume', { sessionId }); Defensive patterns
Strategy: retry
Validate before calling
// Only resume once the client reports readiness
if (!client.ready || !client.resumeSessionHandler) {
await client.waitForReady();
} Type guard
function canResume(c: { resumeSessionHandler?: unknown }): c is { resumeSessionHandler: Function } {
return typeof c.resumeSessionHandler === 'function';
} Try / catch
try {
await rpc.call(method, { sessionId });
} catch (e) {
if (e.message === 'Resume session handler not available') {
await delay(250);
return rpc.call(method, { sessionId }); // retry once ready
} throw e;
} Prevention
- Gate resume calls on client readiness signals
- Wire handlers before registering RPC methods
- Add a small startup delay/retry after daemon boot
When it happens
Trigger: Invoking the resume-session RPC during client startup before connect()/setRPCHandlers has assigned this.resumeSessionHandler; resuming right after teardown/disconnect cleared the handler.
Common situations: Race between daemon startup and an immediate resume request from the app; reconnect flow where RPC registration runs before handler wiring; tests calling the RPC before full initialization.
Related errors
- Backend has been disposed
- ACP session is not started
- The chosen rewind point is no longer present in the source C
- Unsupported Claude goal action
- Claude goal action already in progress
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/a286116a90eb1119.
Report an issue: GitHub.