{"record":{"id":"97c8472978eac922","repo":"astrid-runtime/astrid","slug":"job-exceeded-the-timeout-secs-s-wall-clock-ceilin","errorCode":null,"errorMessage":"job exceeded the {timeout_secs}s wall-clock ceiling","messagePattern":"job exceeded the (.+?)s wall-clock ceiling","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/agent/spawn.rs","lineNumber":181,"sourceCode":"\n    client\n        .send_input(job.to_string())\n        .await\n        .context(\"failed to submit job\")?;\n\n    let drained = tokio::time::timeout(\n        Duration::from_secs(timeout_secs),\n        drain_until_final(&mut client, session),\n    )\n    .await;\n\n    let result = match drained {\n        Ok(inner) => inner,\n        Err(_elapsed) => {\n            // Cooperative cancel so the react capsule aborts the in-flight turn\n            // promptly; delete (which reclaims) is the hard stop regardless.\n            let _ = send_cancel(&mut client, session).await;\n            Err(anyhow!(\n                \"job exceeded the {timeout_secs}s wall-clock ceiling\"\n            ))\n        },\n    };\n\n    // Best-effort disconnect; the connection also closes on drop.\n    let disconnect = astrid_types::ipc::IpcMessage::new(\n        astrid_types::Topic::client_disconnect(),\n        astrid_types::ipc::IpcPayload::Disconnect {\n            reason: Some(\"spawn\".to_string()),\n        },\n        session.0,\n    );\n    let _ = client.send_message(disconnect).await;\n\n    result\n}\n","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/agent/spawn.rs#L163-L199","documentation":"Raised in run_job_under when the job's response stream does not complete before the user-configured wall-clock timeout. Before returning the error, the code sends a cooperative cancel so the daemon aborts the in-flight turn promptly (delete remains the hard stop).","triggerScenarios":"The submitted job takes longer than timeout_secs to produce its final marker: a very long agent turn, a hung upstream model call, or a timeout set too low for the workload.","commonSituations":"Running long analysis jobs with the default short timeout, a daemon stalled on a slow upstream API, or a typo'd job that blocks waiting for input.","solutions":["Increase the --timeout value to cover the expected job duration","Check the daemon logs to see whether the job was hung vs genuinely slow","Split the job into smaller steps; cancel/delete the agent if it is wedged"],"exampleFix":"// before\nastrid-agent spawn --job big-refactor --timeout 30\n// after\nastrid-agent spawn --job big-refactor --timeout 600","handlingStrategy":"retry","validationCode":"// estimate expected duration and pick a timeout with headroom\nlet timeout_secs = std::cmp::max(estimated_secs * 3, 300);","typeGuard":null,"tryCatchPattern":"match run(...).await { Err(e) if e.to_string().contains(\"wall-clock ceiling\") => { eprintln!(\"timed out; retrying with a larger --timeout\"); run_with_timeout(timeout_secs * 4).await }, other => other }","preventionTips":["Set --timeout generously for long-running jobs","Monitor daemon logs for slow or stalled turns","Break large jobs into smaller incremental steps"],"tags":["timeout","cli"],"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"}