{"record":{"id":"9bf1a4b280f3fb8d","repo":"astrid-runtime/astrid","slug":"ipc-write-timed-out","errorCode":null,"errorMessage":"IPC write timed out","messagePattern":"IPC write timed out","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-uplink/src/native/mod.rs","lineNumber":546,"sourceCode":"        frame\n            .as_object_mut()\n            .expect(\"wire frame is an object\")\n            .insert(\n                \"principal\".to_owned(),\n                serde_json::Value::String(principal.clone()),\n            );\n    }\n    let bytes = serde_json::to_vec(&frame)\n        .map_err(|error| std::io::Error::other(format!(\"serialize IPC message: {error}\")))?;\n    let len = u32::try_from(bytes.len())\n        .map_err(|_| std::io::Error::other(\"IPC message exceeds 4 GiB\"))?;\n    tokio::time::timeout(WRITE_TIMEOUT, async {\n        writer.write_all(&len.to_be_bytes()).await?;\n        writer.write_all(&bytes).await?;\n        writer.flush().await\n    })\n    .await\n    .map_err(|_| std::io::Error::new(std::io::ErrorKind::TimedOut, \"IPC write timed out\"))?\n}\n\nfn publish_lifecycle(event_bus: &EventBus, topic: Topic, principal: &str, reason: Option<&str>) {\n    let payload = match reason {\n        Some(reason) => IpcPayload::Disconnect {\n            reason: Some(reason.to_owned()),\n        },\n        None => IpcPayload::Connect,\n    };\n    let message = IpcMessage::new(topic, payload, uuid::Uuid::nil()).with_principal(principal);\n    event_bus.publish(AstridEvent::Ipc {\n        metadata: EventMetadata::new(EVENT_SOURCE),\n        message,\n    });\n}\n","sourceCodeStart":528,"sourceCodeEnd":562,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-uplink/src/native/mod.rs#L528-L562","documentation":"write_message wraps the framed write (length prefix, payload, flush) in tokio::time::timeout(WRITE_TIMEOUT). If the write does not complete within that window, the library converts the elapsed future into a TimedOut io::Error with this message. It indicates the IPC peer or OS pipe/socket is not draining writes fast enough.","triggerScenarios":"forward_outbound pushes messages to a peer whose read loop is stalled or blocked; the peer process is paused (SIGSTOP), deadlockeds, or its receive buffer is full; the socket/pipe is congested with a large backlog; WRITE_TIMEOUT is too small for very large payloads on slow media.","commonSituations":"Deadlocked child process not reading its IPC stdin/socket; very large messages exceeding the timeout budget on a loaded machine; peer stopped by a debugger breakpoint; system under heavy load starving the tokio runtime.","solutions":["Investigate why the peer is not reading: check for a blocked or deadlocked read loop on the receiving side","Increase WRITE_TIMEOUT if payloads are legitimately large or the host is slow","Add backpressure/queueing in forward_outbound instead of blocking on a stalled peer","Monitor and restart the unresponsive peer process"],"exampleFix":"// before\nconst WRITE_TIMEOUT: Duration = Duration::from_secs(5);\n// after: allow larger frames more time\nconst WRITE_TIMEOUT: Duration = Duration::from_secs(30);","handlingStrategy":"retry","validationCode":"// pre-check: is the peer still responsive?\nlet peer_alive = !child_try_wait()?.matches(&ExitStatus::default()); // or poll a ping/pong\nif !peer_alive { restart_peer()?; }","typeGuard":null,"tryCatchPattern":"match write_message(&mut writer, &payload).await {\n    Err(e) if e.kind() == io::ErrorKind::TimedOut => {\n        // peer stalled: attempt bounded retry, then recycle the peer\n        if retries < MAX_RETRIES { retry_after_backoff().await?; }\n        else { restart_peer().await?; }\n    }\n    other => other?,\n}","preventionTips":["Keep the peer's read loop always draining its IPC input","Size WRITE_TIMEOUT for your largest legitimate payload plus slack","Add heartbeats to detect stalled peers early","Avoid blocking the tokio runtime with heavy work between reads/writes"],"tags":["ipc","timeout","network"],"backgroundTag":"request-timeout","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}