{"record":{"id":"214ea653acff4c7a","repo":"Hmbown/CodeWhale","slug":"rate-limit-interruption-should-preserve-checkpoint","errorCode":null,"errorMessage":"rate-limit interruption should preserve checkpoint","messagePattern":"rate-limit interruption should preserve checkpoint","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/tests.rs","lineNumber":9400,"sourceCode":"        \"rate-limit retries should be owned by the sub-agent retry loop\"\n    );\n    let snapshot = {\n        let manager = manager.read().await;\n        manager\n            .get_result(&agent_id)\n            .expect(\"agent should stay registered\")\n    };\n    let SubAgentStatus::Interrupted(reason) = &snapshot.status else {\n        panic!(\"expected interrupted sub-agent, got {:?}\", snapshot.status);\n    };\n    assert!(\n        reason.contains(\"rate-limited provider response\"),\n        \"reason should name the provider rate limit: {reason}\"\n    );\n    let checkpoint = snapshot\n        .checkpoint\n        .as_ref()\n        .expect(\"rate-limit interruption should preserve checkpoint\");\n    assert_eq!(checkpoint.reason, \"api_rate_limited\");\n    assert!(checkpoint.continuable);\n    assert!(snapshot.needs_input.is_some());\n}\n\n#[tokio::test]\nasync fn spawn_duplicate_session_name_error_names_conflicting_agent() {\n    // #2656: the duplicate-name error must identify the conflicting agent so a\n    // model can recover deterministically (reuse the id, or pick a new name).\n    let manager = Arc::new(RwLock::new(SubAgentManager::new(PathBuf::from(\".\"), 5)));\n    let boot_id = manager.read().await.session_boot_id().to_string();\n    let (input_tx, _input_rx) = mpsc::unbounded_channel();\n    let mut existing = SubAgent::new(\n        \"test_agent_existing\".to_string(),\n        FleetRole::Scout,\n        \"scan\".to_string(),\n        make_assignment(),\n        \"deepseek-v4-flash\".to_string(),","sourceCodeStart":9382,"sourceCodeEnd":9418,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/tests.rs#L9382-L9418","documentation":"The interrupted sub-agent's snapshot has `checkpoint: None`, so `.expect(\"rate-limit interruption should preserve checkpoint\")` panics. The library contract is that a rate-limited interruption records a resumable checkpoint (reason \"api_rate_limited\", continuable) plus a needs_input marker. A missing checkpoint means the interruption path skipped persistence.","triggerScenarios":"The sub-agent is interrupted with reason containing \"rate-limited provider response\" but the code path that builds the checkpoint (reason=api_rate_limited, continuable=true) was not executed — e.g. the interruption aborted before snapshotting conversation state.","commonSituations":"Refactoring the retry loop to bail out instead of checkpointing; a new early-return on provider 429 responses; checkpoint persistence failing silently and leaving the field None.","solutions":["Locate the interruption handler that sets SubAgentStatus::Interrupted and confirm it also builds and stores the checkpoint","Verify the checkpoint reason is set to \"api_rate_limited\" and continuable=true on the rate-limit path","Check whether checkpoint serialization/persistence errors are swallowed, leaving checkpoint None","Add an assertion or log immediately after interruption to confirm the checkpoint was written"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"assert!(snapshot.checkpoint.is_some(), \"interrupted agent must carry a checkpoint\");","typeGuard":"fn resumable(s: &SubAgentSnapshot) -> bool { matches!(&s.status, SubAgentStatus::Interrupted(_)) && s.checkpoint.as_ref().map(|c| c.continuable).unwrap_or(false) }","tryCatchPattern":"let cp = snapshot.checkpoint.as_ref().ok_or_else(|| anyhow!(\"rate-limit interruption lost checkpoint for {:?}\", snapshot.status))?;","preventionTips":["Make the interruption handler build the checkpoint before constructing Interrupted status","Never swallow checkpoint persistence errors","Unit-test the rate-limit path's checkpoint fields (reason, continuable) directly","Keep checkpoint construction in one shared helper so new interruption paths cannot skip it"],"tags":["rust","testing","resumability"],"backgroundTag":"internal-invariant-violation","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}