Hmbown/CodeWhale · error
sentinel
Error message
sentinel
What it means
A panic from `.expect("sentinel")` on `std::fs::write(tmp.path().join("sentinel.txt"), sentinel)` in crates/tui/src/tools/subagent/tests.rs:8588. The planner test writes a sentinel file to prove that `agent_planner` may dispatch a bounded read (`cat sentinel.txt`); failure of the fixture write panics the test before dispatch. The expect message is the test's claim that writing the sentinel is trivially safe setup.
Solutions
- Ensure the TempDir guard outlives the write — keep `tmp` alive for the whole test body.
- Confirm TMPDIR is writable and has free space; set TMPDIR explicitly if the default is constrained.
- Check no earlier code replaced sentinel.txt with a directory or removed the temp dir.
- Wrap the write with context (unwrap_or_else) so future failures name the path and io error.
Example fix
// before
std::fs::write(tmp.path().join("sentinel.txt"), sentinel).expect("sentinel");
// after
let p = tmp.path().join("sentinel.txt");
std::fs::write(&p, sentinel).unwrap_or_else(|e| panic!("sentinel write failed at {}: {e}", p.display())); Defensive patterns
Strategy: try-catch
Validate before calling
let p = tmp.path().join("sentinel.txt");
assert!(!p.exists() || p.is_file(), "sentinel path must not be a directory");
assert!(tmp.path().is_dir(), "tempdir must exist before sentinel write"); Type guard
fn can_write(dir: &std::path::Path) -> bool {
let probe = dir.join(".probe");
std::fs::write(&probe, b"").is_ok().then(|| std::fs::remove_file(&probe).ok()).is_some()
} Try / catch
std::fs::write(&p, sentinel)
.unwrap_or_else(|e| panic!("sentinel fixture failed at {}: {e}", p.display())); Prevention
- Order fixture writes immediately after tempdir creation, before any code that could drop `tmp`.
- Include the failing path and io error in the panic message.
- Ensure CI temp mounts are writable and sized for parallel test load.
- Prove reads with sentinels only after confirming the write succeeded (assert on metadata).
When it happens
Trigger: Writing the sentinel into the temp workspace when the TempDir has already been dropped, the path exists as a directory, the filesystem is full or read-only, or permission bits on the temp dir deny the write.
Common situations: TMPDIR on a full tmpfs in CI, tests refactored so `tmp` is consumed/moved before the write, or sandbox policies restricting writes outside whitelisted paths.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- sentinel fixture
- canonical temp root
- Codex client
- credential fixture
- planner must dispatch a bounded read
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/107786d1946e4088.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/tests.rs:8588
);
for command in ["pwd", "git status --short", "rg needle crates"] {
assert!(
registry
.envelope_refusal("bash", &json!({"command": command}))
.is_none(),
"planner should admit {command}"
);
}
for command in ["rm -rf crates", "git push origin main", "bash -lc 'id'"] {
assert!(
registry
.envelope_refusal("bash", &json!({"command": command}))
.is_some(),
"planner must refuse {command}"
);
}
let sentinel = "PLANNER_PROBE_SENTINEL";
std::fs::write(tmp.path().join("sentinel.txt"), sentinel).expect("sentinel");
let output = registry
.execute(
"agent_planner",
"bash",
json!({"command": "cat sentinel.txt"}),
)
.await
.expect("planner must dispatch a bounded read");
assert_eq!(output, sentinel);
}
#[tokio::test]
async fn scout_shell_respects_parent_shell_and_network_ceilings() {
let tmp = tempdir().expect("tempdir");
let mut shell_off =
stub_runtime().with_agent_tool_surface_options(enabled_agent_surface_options());
shell_off.context = ToolContext::new(tmp.path().to_path_buf());
shell_off.allow_shell = false;View on GitHub (pinned to 433685b202)