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

  1. Ensure the TempDir guard outlives the write — keep `tmp` alive for the whole test body.
  2. Confirm TMPDIR is writable and has free space; set TMPDIR explicitly if the default is constrained.
  3. Check no earlier code replaced sentinel.txt with a directory or removed the temp dir.
  4. 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

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


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)