fix: remove debug_assert guards that panic on valid error paths - #1385
Conversation
Two debug_assert! calls added in #1312 fire on expected runtime error paths (not programmer bugs), turning graceful error returns into panics in debug/test builds: - state.rs: Completed→Cancelled is a user-facing error handled by transition_to() returning Err — not a bug - execute.rs: empty tool_name from malformed LLM output is handled by ToolError::NotFound — not a bug Removes both asserts; keeps the circuit-breaker assert (genuinely guards a caller invariant). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request refactors error handling by removing Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request correctly removes two debug_assert! calls that were causing panics in debug builds for what should be handled as recoverable runtime errors. In src/context/state.rs, an invalid job state transition is now consistently handled by returning a Result::Err, which is appropriate for user-facing error paths. In src/tools/execute.rs, an empty tool name, which can result from malformed LLM output, is now gracefully handled by the existing logic that returns a ToolError::NotFound. These changes improve the robustness of the error handling by correctly distinguishing between programmer errors (invariants) and expected runtime failures.
There was a problem hiding this comment.
Pull request overview
This PR removes debug_assert! invariant guards that were firing on expected runtime error paths, causing debug/test builds to panic instead of returning graceful errors. It restores the intended behavior for job state transitions and tool execution when inputs are malformed.
Changes:
- Removed the
debug_assert!guarding emptytool_nameinexecute_tool_with_safety, allowing the existingToolError::NotFoundpath to handle malformed calls. - Removed the
debug_assert!guarding invalid job state transitions inJobContext::transition_to, allowing the existingErr(...)return to handle user-facing invalid transitions. - Updated the empty-tool-name regression test comment to reflect “graceful error, not panic” behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/tools/execute.rs | Removes the empty-tool-name debug_assert! and adjusts the related regression test comment. |
| src/context/state.rs | Removes the state-transition debug_assert! so invalid transitions return Err instead of panicking in debug/test. |
Comments suppressed due to low confidence (1)
src/tools/execute.rs:30
- With the debug_assert removed, an empty
tool_namenow returnsToolError::NotFound { name: "" }, which formats asTool not found(blank tool name) and is hard to diagnose. Consider special-casingtool_name.is_empty()to return a clearer error (e.g., use a placeholder like "" in the NotFound name or return InvalidParameters with an explicit message).
let tool = tools
.get(tool_name)
.await
.ok_or_else(|| crate::error::ToolError::NotFound {
name: tool_name.to_string(),
})?;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review feedback: assert the specific error variant instead of just is_err() so the regression test actually enforces the expected error path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Removes debug_assert! invariant guards that were triggering panics on expected runtime error paths in debug/test builds, restoring graceful error handling for invalid job state transitions and malformed tool calls.
Changes:
- Removed a
debug_assert!inexecute_tool_with_safetyso empty/malformedtool_namereturnsToolError::NotFoundinstead of panicking in debug/test. - Removed a
debug_assert!inJobContext::transition_toso invalid (but user-triggerable) state transitions returnErrwithout panicking. - Strengthened the regression test to assert the exact error variant returned for an empty tool name.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/tools/execute.rs | Removes debug panic path for empty tool names and updates regression test expectations. |
| src/context/state.rs | Removes debug panic path for invalid job state transitions while keeping graceful error return. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ai#1385) * fix: remove debug_assert guards that panic on valid error paths (nearai#1312) Two debug_assert! calls added in nearai#1312 fire on expected runtime error paths (not programmer bugs), turning graceful error returns into panics in debug/test builds: - state.rs: Completed→Cancelled is a user-facing error handled by transition_to() returning Err — not a bug - execute.rs: empty tool_name from malformed LLM output is handled by ToolError::NotFound — not a bug Removes both asserts; keeps the circuit-breaker assert (genuinely guards a caller invariant). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: tighten empty tool name test to assert ToolError::NotFound variant Address review feedback: assert the specific error variant instead of just is_err() so the regression test actually enforces the expected error path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ai#1385) * fix: remove debug_assert guards that panic on valid error paths (nearai#1312) Two debug_assert! calls added in nearai#1312 fire on expected runtime error paths (not programmer bugs), turning graceful error returns into panics in debug/test builds: - state.rs: Completed→Cancelled is a user-facing error handled by transition_to() returning Err — not a bug - execute.rs: empty tool_name from malformed LLM output is handled by ToolError::NotFound — not a bug Removes both asserts; keeps the circuit-breaker assert (genuinely guards a caller invariant). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: tighten empty tool name test to assert ToolError::NotFound variant Address review feedback: assert the specific error variant instead of just is_err() so the regression test actually enforces the expected error path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ai#1385) * fix: remove debug_assert guards that panic on valid error paths (nearai#1312) Two debug_assert! calls added in nearai#1312 fire on expected runtime error paths (not programmer bugs), turning graceful error returns into panics in debug/test builds: - state.rs: Completed→Cancelled is a user-facing error handled by transition_to() returning Err — not a bug - execute.rs: empty tool_name from malformed LLM output is handled by ToolError::NotFound — not a bug Removes both asserts; keeps the circuit-breaker assert (genuinely guards a caller invariant). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: tighten empty tool name test to assert ToolError::NotFound variant Address review feedback: assert the specific error variant instead of just is_err() so the regression test actually enforces the expected error path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ai#1385) * fix: remove debug_assert guards that panic on valid error paths (nearai#1312) Two debug_assert! calls added in nearai#1312 fire on expected runtime error paths (not programmer bugs), turning graceful error returns into panics in debug/test builds: - state.rs: Completed→Cancelled is a user-facing error handled by transition_to() returning Err — not a bug - execute.rs: empty tool_name from malformed LLM output is handled by ToolError::NotFound — not a bug Removes both asserts; keeps the circuit-breaker assert (genuinely guards a caller invariant). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: tighten empty tool name test to assert ToolError::NotFound variant Address review feedback: assert the specific error variant instead of just is_err() so the regression test actually enforces the expected error path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
debug_assert!calls from fix: add debug_assert invariant guards to critical code paths #1312 that fire on expected runtime error paths, turning graceful error returns into panics in debug/test buildsstate.rs:Completed→Cancelledis a user-facing error (cancel a completed job) — handled bytransition_to()returningErr, not a bugexecute.rs: emptytool_namefrom malformed LLM output — handled byToolError::NotFound, not a bugdebug_assert(genuinely guards a caller invariant)Fixes the 2 test failures on staging CI:
tools::builtin::job::tests::test_cancel_job_completedtools::execute::tests::test_execute_empty_tool_name_returns_not_foundTest plan
cargo clippy --all --benches --tests --examples --all-features— zero warnings🤖 Generated with Claude Code