can1357/oh-my-pi · error · Error
Socket not ready after
Error message
Socket not ready after ${timeoutMs}ms What it means
The readiness poll for a DAP adapter's endpoint timed out: the check() predicate never succeeded within timeoutMs even though the process did not exit. The client gives up rather than blocking forever on an adapter that never becomes reachable.
Solutions
- Increase the connect/startup timeoutMs passed to DapClient.connect or the session launch call
- Inspect adapter stdout/stderr to confirm it is actually starting and what it is waiting on
- Fix host/port configuration so the readiness check probes the correct endpoint
- Pre-warm or speed up adapter startup (fix AV exclusions, remove first-run compiles) if it is genuinely slow
Example fix
// before
const client = await DapClient.connect({ adapter, cwd, timeoutMs: 5000 });
// after
const client = await DapClient.connect({ adapter, cwd, timeoutMs: 30_000 }); // slow cold start Defensive patterns
Strategy: validation
Validate before calling
if (adapter.slowStart) timeoutMs = Math.max(timeoutMs, 60_000);
Try / catch
try {
await DapClient.connect({ adapter, cwd, timeoutMs });
} catch (err) {
if (String((err as Error).message).startsWith('Socket not ready')) {
// retry once with a longer window before giving up
return await DapClient.connect({ adapter, cwd, timeoutMs: timeoutMs * 3 });
}
throw err;
} Prevention
- Set startup timeouts generously (30s+) for heavyweight adapters
- Watch adapter stdout for readiness lines ('listening at ...') to confirm it is starting
- Fix host/port config so readiness probes hit the right endpoint
- Pre-warm adapters or cache started instances to avoid repeated cold starts
When it happens
Trigger: Adapter process runs but never opens the awaited socket/port within timeoutMs; check() keeps failing while the deadline elapses (slow machine, wrong port file, adapter waiting on stdin handshake that never comes); timeoutMs configured too low for a heavy adapter startup.
Common situations: Cold-start of a large adapter (first-run compile, antivirus scanning) exceeding the default timeout; adapter launched but waiting for input before listening; misconfigured host/port so the probe polls the wrong endpoint; debugger startup delayed under heavy system load.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Adapter process exited before socket was ready
- Adapter process exited before TCP port
- DAP adapter exited before write completed
- DAP adapter is not running
- No active stack frame. Run stack_trace first or supply…
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/2724da8522523a83.
Report an issue: GitHub.
Appendix: source
Thrown at packages/coding-agent/src/dap/client.ts:783
throw error;
}
}
/** Poll a condition until it returns true, or timeout/process exit. */
async function waitForCondition(
check: () => boolean | Promise<boolean>,
timeoutMs: number,
proc: { exitCode: number | null },
): Promise<void> {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
if (await check()) return;
if (proc.exitCode !== null) {
throw new Error("Adapter process exited before socket was ready");
}
await Bun.sleep(50);
}
throw new Error(`Socket not ready after ${timeoutMs}ms`);
}
/** Connect once to a TCP DAP server. */
async function connectTcpSocket(host: string, port: number, onClose?: () => void): Promise<SocketTransport> {
const { promise, resolve, reject } = Promise.withResolvers<SocketTransport>();
let streamController: ReadableStreamDefaultController<Uint8Array>;
let opened = false;
const readable = new ReadableStream<Uint8Array>({
start(controller) {
streamController = controller;
},
});
void Bun.connect({
hostname: host,
port,
socket: {
open(socket) {View on GitHub (pinned to 9690622007)