--- id: "bug-1761" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "scheduler" severity: "unknown" timestamp: "2026-09-02T04:30:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/scheduler/src/repl_break.c (repl_cmd_delete)"] tags: ["repl", "scheduler-sim", "cli-ux", "input-validation", "fail-loud"] related: [] legacy: true --- # bug-1761: cli-ux audit of xce_scheduler's --interactive REPL (scheduler-sim-repl-verbosity spec discussion)… ## Description cli-ux audit of xce_scheduler's --interactive REPL (scheduler-sim-repl-verbosity spec discussion): repl_cmd_delete() (repl_break.c) parses its argument with atoi(), which silently returns 0 on non-numeric input instead of signalling an error -- `delete abc` reports "[sim] delete: no breakpoint with id 0" (a well-formed-but-missing-id message) rather than rejecting "abc" as not a number, masking an operator typo as a legitimate lookup miss. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause CONFIRMED via source read: repl_cmd_delete() used `int id = atoi(tokens[1]);` with no validation of atoi()'s return, unlike this file family's own documented "fail loud" convention -- repl.c's repl_cmd_step() doc comment explicitly rejects the equivalent atoi()-style silent-coercion failure mode and uses strtol()+endptr instead specifically to catch non-numeric/trailing-garbage input. delete's atoi() call was never updated to match when that convention was established, so `delete abc`/`delete 1x` both silently coerced to some numeric prefix (or 0) instead of erroring. ## Fix FIXED. repl_cmd_delete() (repl_break.c) now uses strtol()+endptr, mirroring repl_cmd_step()'s exact validation shape: rejects a token with no valid leading integer, trailing non-numeric garbage, or a non-positive value (breakpoint ids are assigned via pre-incremented next_bp_id in repl_cmd_break(), so 1 is the smallest id that can ever legitimately exist), printing "[sim] delete: '' is not a valid breakpoint id -- usage: delete |all" instead of silently proceeding. Added test_delete_non_numeric_id_rejected (test_repl_breakpoints_inspection.c, registered via RUN_TEST) covering "abc", "0", "-1", and "1x", all asserting the existing breakpoint is left untouched. Verified via /xce-build scheduler: clean compile, test_delete_non_numeric_id_rejected PASSed (testlog.txt confirms all 4 cases -- "abc", "0", "-1", "1x" -- hit the new rejection path), sched_repl_breakpoints_inspection_test suite OK. One unrelated pre-existing failure in the same run (test_job_rusage_reconciles_mem_reservation_against_usage, test_core_events.c) -- different file, different subsystem (mem-reservation reconciliation, not REPL/breakpoint parsing), not touched by this fix. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._