Repository navigation
Fix recall_file panic on out-of-range lines; guard each request - #57
Merged
Merged
Conversation
…ly, and a panic in one request no longer ends the server recall_file sliced the source with a start five or more lines past the end of the file, or far enough after its end_line, and panicked. The server exited with status 101 and answered nothing after that, so every Lumen tool was gone for the rest of the session. A range the file cannot satisfy is now an invalid-params error that states the file's line count and what was asked, an end past the last line is clamped to it, and the arithmetic saturates. A range the file can satisfy is answered byte for byte as before. Each request now runs under a panic guard. A panic is answered with an internal error, filed as a request_panic fault (the tool, the path, and the file and line it panicked at, never the panic message, which can quote the text being read), and the repeat-read memory of the call is dropped. lumen report ranks the new kind just below a fired fail-open guard.
…start_line 0 still answers The changelog said any range on an empty file was refused. A start_line of 0 is not: it reads from line 1, which on an empty file is the empty window. The unit test now pins that case next to the refused ones.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
recall_filewith astart_linefive or more lines past the end of the file, or well after itsend_line, panicked onsrc_lines[ctx_start..ctx_end]. The server exited with status 101 and never answered again, so one bad guess took every Lumen tool away for the rest of the session.range_window) now resolves the window. A range the file cannot satisfy is an error reply that states the file's line count and what was asked. Anend_linepast the last line clamps to it. The arithmetic saturates (u64::MAX,i64::MAX).The range error is a JSON-RPC error frame (
-32602, like the other argument errors inlib.rs), not anisError: trueresult:lib.rshas no such reply for a tool failure. A caught panic is-32603.Red to green
Real binary over stdio (
crates/lumen-mcp/tests/recall_range.rs). After every bad request a valid one is sent and must be answered. Written first, run against the unfixed code: 5 failed, 3 passed.u64::MAX/i64::MAXUnit tests on the window logic cannot compile against the old inline code, so they ran against a stub restating the old arithmetic: 9 failed, 113 passed. The lib now has 135 passing.
Valid requests are byte-identical
The base-commit binary against this branch, 48 requests over rs, ts, py and log fixtures:
smart_read(outline, full),recall_file(name, names, no selector, ranges, end clamps, start 0),compress_logs(path, text). Every reply is identical, and so are the tokens.A differential test and a property test over every accepted range pin it in the suite. No existing test was edited.
Behavior that changes
Three requests were answered before with something other than what they asked for, and now get the error: a start one to four lines past the end (the last lines, or nothing), a start up to seven lines after the end (a window around lines nobody named), and a range that starts at line 1 or later on an empty file.
start_line0 is unchanged (read from line 1; on an empty file, the empty window). No schema change.Audit
Every index, slice, arithmetic and unwrap that tool arguments or file contents reach:
recall_file(range, names, no selector),smart_read(outline, full, unknown mode, ranked outline),compress_logs(path, text). The range slice is the only panic found.Results filed asmeter_write_failed.compress_logs: no panic (no_tool_panics_on_an_odd_fileand two siblings). A non-UTF-8 file is an error reply; wrong-typed arguments are invalid params.safe_readhas no size cap; left as is.Panic guard
Added, because the audit cannot prove the parser-driven paths panic-free and one panic ends every tool.
dispatch_guardedwrapsdispatchper request, andmain.rscalls it. A panic is answered with-32603("the server is still running"), printed on stderr, and filed as a fault, not swallowed.request_panic: tool name, path (capped at 4096 chars), andpanicked at file:line:colfrom a panic hook. The panic message is in the reply and on stderr but not in the fault: it can quote the text being read, and reports hold no file contents (a_fault_for_a_panic_never_carries_the_text_the_call_was_reading).LUMEN_CAPTURE=0is honored; a missing or unwritable spool says so on stderr.report.rs(FAULT_KINDS,kind_priorityrank 1 below a fired fail-open guard,impact,headline) with tests; README and CHANGELOG updated. The doctor has no per-kind code. No allowlist entry: the silent-fallback guard is unchanged and green.guarded, and a differential test shows it changes no answer that did not panic. Also run once on a binary with the range check removed: both panicking calls answered-32603, later calls were answered, two records reached the spool, none withLUMEN_CAPTURE=0.Verified
The local gate (fmt, clippy with warnings denied, every crate's tests, frontend, e2e, MSRV build) is green on
b10980b. It ran withLUMEN_RANKED_TIME_BUDGET_MS=60000because the machine's load was above 50; CI runs without it. Run on macOS only.