{"record":{"id":"6b49c02308eb16c2","repo":"Hmbown/CodeWhale","slug":"user-input-request-has-an-indeterminate-termi","errorCode":null,"errorMessage":"User-input request '{}' has an indeterminate terminal receipt; inspect Runtime storage before completing turn '{turn_id}'","messagePattern":"User-input request '(.+?)' has an indeterminate terminal receipt; inspect Runtime storage before completing turn '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":2954,"sourceCode":"        let key = (thread_id.to_string(), input_id.to_string());\n        let mut pending = self.pending_user_inputs.lock();\n        if pending.get(&key).is_some_and(|entry| !entry.settling) {\n            pending.remove(&key);\n        }\n    }\n\n    fn claim_pending_user_inputs_for_turn(\n        &self,\n        thread_id: &str,\n        turn_id: &str,\n    ) -> Result<(Vec<PendingUserInputRequest>, Vec<watch::Receiver<u64>>)> {\n        let mut pending = self.pending_user_inputs.lock();\n        if let Some((_, entry)) = pending.iter().find(|((pending_thread_id, _), entry)| {\n            pending_thread_id == thread_id\n                && entry.request.turn_id == turn_id\n                && entry.indeterminate\n        }) {\n            bail!(\n                \"User-input request '{}' has an indeterminate terminal receipt; inspect Runtime storage before completing turn '{turn_id}'\",\n                entry.request.id\n            );\n        }\n        let mut claims = Vec::new();\n        let mut settling = Vec::new();\n        for ((pending_thread_id, _), entry) in pending.iter_mut() {\n            if pending_thread_id != thread_id || entry.request.turn_id != turn_id {\n                continue;\n            }\n            if entry.settling {\n                settling.push(entry.settlement_tx.subscribe());\n                continue;\n            }\n            entry.settling = true;\n            claims.push(entry.request.clone());\n        }\n        Ok((claims, settling))","sourceCodeStart":2936,"sourceCodeEnd":2972,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/runtime_threads.rs#L2936-L2972","documentation":"Thrown while a turn is being completed: a user-input request registered for this (thread_id, turn_id) has entry.indeterminate == true. That flag is set when the durable append of the user's answer failed AND the transactional rollback also failed, so the JSONL event log may or may not already contain the terminal receipt. The runtime fails closed: it refuses to complete the turn because retrying or publishing could duplicate or disclose a response whose receipt cannot be established.","triggerScenarios":"complete_turn / turn-termination path calls claim_pending_user_inputs_for_turn after a prior submit_user_input answer hit a non-retry-safe RuntimeEventAppendError (append failed, rollback failed) and mark_pending_user_input_indeterminate ran. Any later attempt to finish that same turn re-hits the guard at runtime_threads.rs:2949-2958.","commonSituations":"Disk full or permission loss under the runtime store while an answer is being persisted; a crash mid-append; the process was killed between a failed fsync and rollback. The turn is permanently blocked until a human inspects the store.","solutions":["Inspect the thread's JSONL event log on disk (Runtime storage) and determine whether the answer receipt line was written","If the line exists, clear the tombstone by reconciling storage (restart the runtime after fixing the storage issue so state is re-derived), otherwise repair/delete the partial tail","Fix the root storage cause (disk space, permissions, path) before restarting, or the flag will be set again on the next failure","Do not write code that retries complete_turn against this error - the guard exists precisely to stop duplicate terminal receipts"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// In the turn-completion caller: this error is terminal, never retry it.\nmatch manager.complete_turn(thread_id, turn_id).await {\n    Ok(_) => {}\n    Err(e) if e.to_string().contains(\"indeterminate terminal receipt\") => {\n        // Fail closed: surface to an operator and inspect the JSONL store.\n        tracing::error!(%thread_id, %turn_id, error = %e, \"turn frozen: inspect Runtime storage\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep the runtime store on reliable storage; ENOSPC/EACCES during an answer append is what creates indeterminate tombstones","Quiesce in-flight user-input answers before shutdown so appends are not interrupted mid-write","Treat any 'indeterminate receipt' message as a data-integrity incident requiring human inspection, never as retryable"],"tags":["user-input","turn-lifecycle","data-integrity","fail-closed","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"}