{"record":{"id":"c54746353e7b7d55","repo":"Hmbown/CodeWhale","slug":"bounded-to-model-output-cap","errorCode":null,"errorMessage":"bounded to model output cap","messagePattern":"bounded to model output cap","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/budget_handback.rs","lineNumber":165,"sourceCode":"            return Err(\"a hand-back turn is already in flight\");\n        }\n        let available =\n            narrow_optional_limit(self.available_worker_tokens(worker, false), local_remaining)\n                .unwrap_or(allowance)\n                .min(allowance);\n        let output = available\n            .saturating_sub(input_tokens)\n            .min(u64::from(output_cap));\n        if output < MIN_HAND_BACK_OUTPUT {\n            return Err(\n                \"remaining token allowance cannot cover the estimated report input and output\",\n            );\n        }\n        let reservation = Arc::new(input_tokens.saturating_add(output));\n        self.handback_reservations\n            .insert(worker.to_string(), Arc::downgrade(&reservation));\n        Ok((\n            u32::try_from(output).expect(\"bounded to model output cap\"),\n            reservation,\n        ))\n    }\n}\n\npub(super) enum Outcome {\n    Report { text: String, usage_reported: bool },\n    Fallback(String),\n    Cancelled,\n}\n\npub(super) fn repair_stopped_tool_calls(messages: &mut Vec<Message>, cause: &str) {\n    let final_calls = messages\n        .iter()\n        .rev()\n        .find(|message| message.role == Role::Assistant)\n        .into_iter()\n        .flat_map(|message| &message.content)","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/budget_handback.rs#L147-L183","documentation":"In `reserve_handback` (crates/tui/src/tools/subagent/budget_handback.rs:165), the computed output token count is converted from `u64`/`usize` to `u32` with `u32::try_from(...).expect(\"bounded to model output cap\")`. The invariant is that output token counts never exceed the model output cap, so they always fit in `u32`. A panic here means that invariant was violated — the reservation computed an output value larger than `u32::MAX`.","triggerScenarios":"Calling `reserve_handback` (via budget handback coverage markers or shared-ancestor/source-cap reservation paths) when the estimated output tokens computed from input tokens saturate or are otherwise unbounded, exceeding `u32::MAX`.","commonSituations":"A misconfigured model output cap (e.g. a cap parsed as a sentinel like `u64::MAX` or a bogus config value), or an arithmetic path that saturates `usize` before the conversion.","solutions":["Verify the model output cap configured for the worker is a sane, finite value.","Clamp the computed `output` to the model output cap before the conversion.","Replace the `expect` with an explicit error return if unbounded estimates are possible.","Add a test asserting reservations stay within the configured output cap."],"exampleFix":"// before\nu32::try_from(output).expect(\"bounded to model output cap\")\n// after\nlet output = output.min(model_output_cap as u64);\nu32::try_from(output).unwrap_or(u32::MAX)","handlingStrategy":"validation","validationCode":"// Guard before reserving: output must fit u32\nfn output_fits_u32(output: u64) -> bool { output <= u32::MAX as u64 }","typeGuard":"fn bounded_output(output: u64) -> Option<u32> { u32::try_from(output).ok() }","tryCatchPattern":"// Replace expect with explicit clamping and error reporting\nlet out = u32::try_from(output)\n    .map_err(|_| ToolError::execution_failed(format!(\"output estimate {output} exceeds model output cap\")))?;","preventionTips":["Clamp output estimates to the configured model output cap before conversion.","Never use sentinel values like u64::MAX for caps in configuration.","Add a unit test that reserves with maximum-size caps.","Audit arithmetic paths that can saturate before the try_from."],"tags":["integer-overflow","invariant","budget","panic"],"backgroundTag":"value-out-of-range","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}