different-ai/openwork · error
OpenWork host connection is not ready.
Error message
OpenWork host connection is not ready.
What it means
connectRealtime in VoicePanel depends on props.client, the OpenWork host connection object used to mint voice realtime sessions. If it is null/undefined the panel cannot create a realtime session, so it throws before doing any network work.
Source
Thrown at apps/app/src/react-app/domains/session/voice/voice-panel.tsx:483
voiceRealtime.pendingResponse = false;
requestRealtimeResponse(channel, false);
} else {
setRuntimeStatus(voiceRealtime.micMuted ? "muted" : "listening");
}
return;
}
if (type === "error") {
voiceRealtime.responseInProgress = false;
const error = readRecord(event, "error");
const message = typeof error.message === "string" ? error.message : "Realtime returned an error.";
addEntry("system", message, { error: true });
setRuntimeStatus("error", message);
}
}, [addEntry, props.sessionId, requestRealtimeResponse, setRuntimeStatus]);
const connectRealtime = useCallback(async (audioInput = true) => {
const client = props.client;
if (!client) throw new Error("OpenWork host connection is not ready.");
if (audioInput && !navigator.mediaDevices?.getUserMedia) throw new Error("Microphone capture is unavailable in this runtime.");
disconnectRealtime(true);
setRuntimeStatus("connecting", "Minting Realtime session...");
const sessionContext = await loadVoiceSessionContext(props.opencodeBaseUrl, props.openworkToken, props.sessionId);
const realtimeSession = await client.createVoiceRealtimeSession({ sessionContext });
const peer = new RTCPeerConnection();
voiceRealtime.peer = peer;
if (audioInput) {
setRuntimeStatus("connecting", "Requesting microphone...");
const macPermissionGranted = await requestMacMicrophoneAccess();
if (!macPermissionGranted) throw new Error("macOS denied microphone access. Enable OpenWork in System Settings > Privacy & Security > Microphone, then restart OpenWork.");
const stream = await navigator.mediaDevices.getUserMedia({
audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true },
});
voiceRealtime.stream = stream;
setMicDiagnostics(stream);View on GitHub (pinned to 2b7df46e8a)
Solutions
- Wait for the host client to be ready (disable the voice button until props.client is set)
- Reconnect the app to the OpenWork host / restart the desktop app if the connection dropped
- Guard the call: if (!client) show a 'connecting…' or retry state instead of throwing raw
- Check host process health/logs if client is persistently null
Example fix
// before
const client = props.client;
if (!client) throw new Error("OpenWork host connection is not ready.");
// after
const client = props.client;
if (!client) {
setRuntimeStatus("error", "Host connection not ready — retrying...");
return;
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!props.client) {
setRuntimeStatus("idle", "Host connection not ready.");
return;
} Type guard
const hasHostClient = (c: typeof props.client): c is NonNullable<typeof props.client> => c != null;
Try / catch
try {
await connectRealtime();
} catch (e) {
if (e instanceof Error && e.message === "OpenWork host connection is not ready.") {
setRuntimeStatus("error", "Reconnect to the OpenWork host and try again.");
} else throw e;
} Prevention
- Disable voice controls until the host client is connected
- Subscribe to host connection state and auto-retry when it becomes ready
- Check client readiness on panel mount
- Show a spinner instead of invoking connect during host startup
When it happens
Trigger: Calling connectRealtime() when props.client is null — typically because the voice panel rendered before the host client finished connecting, or the host (desktop/opencode backend) connection dropped.
Common situations: User clicks the voice connect button while the app is still establishing its host connection; host process crashed or restarted; panel mounted in a state where client was never injected (e.g. headless/web runtime without the bridge).
Related errors
- Microphone capture is unavailable in this runtime.
- Realtime offer did not include SDP.
- macOS denied microphone access. Enable OpenWork in System Se
- OpenAI Realtime SDP failed: ${sdpResponse.status} ${detail}
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/f901d7813903e8a1.
Report an issue: GitHub.