{"record":{"id":"ce3b0d0825bbc86a","repo":"Hmbown/CodeWhale","slug":"dynamic-tool-call-call-id-has-an-indeterminate","errorCode":null,"errorMessage":"Dynamic tool call '{call_id}' has an indeterminate terminal receipt; inspect Runtime storage before retrying","messagePattern":"Dynamic tool call '(.+?)' has an indeterminate terminal receipt; inspect Runtime storage before retrying","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":3253,"sourceCode":"            Some(entry) => entry.sender.send(decision).is_ok(),\n            None => false,\n        }\n    }\n\n    pub async fn deliver_dynamic_tool_result(\n        &self,\n        thread_id: &str,\n        turn_id: &str,\n        call_id: &str,\n        result: DynamicToolCallResult,\n    ) -> Result<bool> {\n        let claim = match self.claim_pending_dynamic_tool(thread_id, turn_id, call_id) {\n            PendingDynamicToolClaim::Claimed(claim) => claim,\n            PendingDynamicToolClaim::Settling(_) | PendingDynamicToolClaim::Missing => {\n                return Ok(false);\n            }\n            PendingDynamicToolClaim::Indeterminate => {\n                bail!(\n                    \"Dynamic tool call '{call_id}' has an indeterminate terminal receipt; inspect Runtime storage before retrying\"\n                );\n            }\n        };\n        let ack =\n            self.spawn_dynamic_tool_settlement(claim, DynamicToolTerminalOutcome::Resolved(result));\n        Ok(Self::await_dynamic_tool_settlement(ack)\n            .await?\n            .result_accepted)\n    }\n\n    pub async fn submit_user_input(\n        &self,\n        thread_id: &str,\n        input_id: &str,\n        response: crate::tools::user_input::UserInputResponse,\n    ) -> Result<bool> {\n        let engine = {","sourceCodeStart":3235,"sourceCodeEnd":3271,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/runtime_threads.rs#L3235-L3271","documentation":"submit_dynamic_tool_result (or the turn path) claimed call_id for (thread_id, turn_id) and got PendingDynamicToolClaim::Indeterminate: the entry's terminal receipt append failed and rolled back uncleanly, so the JSONL log may already contain the terminal line. The runtime refuses a resubmission because a duplicate terminal receipt could be appended.","triggerScenarios":"Retrying submit_dynamic_tool_result after the first attempt's settlement task hit a non-retry-safe RuntimeEventAppendError (mark_dynamic_tool_claim_indeterminate ran). Also reached from turn completion touching the same call. See runtime_threads.rs:3246-3257 and claim_pending_dynamic_tool:3113.","commonSituations":"Storage failure (ENOSPC, EACCES) during the first result append; process crash between append and rollback; client-side auto-retry of a timed-out HTTP submit.","solutions":["Stop retrying the submit - the call is frozen in an indeterminate tombstone by design","Inspect the thread's JSONL event log to see whether tool_call.resolved / tool_call.canceled / tool_call.timeout was durably written for this call_id","Repair the storage cause, then reconcile or remove the tombstoned entry via runtime restart / storage reconciliation","Preserve the inspected evidence; it tells you whether the model ever received the result"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Indeterminate receipt: stop, never resubmit, escalate.\nmatch manager.submit_dynamic_tool_result(thread_id, turn_id, call_id, result).await {\n    Ok(accepted) => Ok(accepted),\n    Err(e) if e.to_string().contains(\"indeterminate terminal receipt\") => {\n        tracing::error!(%call_id, \"result state unknown; inspect Runtime storage before any retry\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Do not auto-retry result submission after storage errors - a failed rollback freezes the call","Keep the runtime store healthy (space, permissions) so appends never enter the failed-rollback path","Log both call_id and turn_id with submissions so an incident can be traced to the exact JSONL line"],"tags":["dynamic-tools","data-integrity","fail-closed","idempotency","runtime"],"backgroundTag":"indeterminate-write-state","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}