Hmbown/CodeWhale · warning

input fixture

Error message

input fixture

What it means

`std::fs::write(&input_path, "b\na\n").expect("input fixture")` in the `read_only_inspection_roles_cannot_write_through_text_filters` test (crates/tui/src/tools/subagent/tests.rs:8237) writes the test's input file into the temp dir. It panics if the write fails — the fixture file is assumed writable by setup. Failure is environmental or a path bug.

Solutions

  1. Confirm the temp dir is created and still alive at the point of the write (don't drop the TempDir guard).
  2. Check disk space and mount flags for the temp location.
  3. Ensure `input_path` doesn't collide with an existing directory.
  4. Improve the panic message to include the full path and OS error for diagnosis.

Example fix

// before
std::fs::write(&input_path, "b\na\n").expect("input fixture");
// after
std::fs::write(&input_path, "b\na\n")
    .unwrap_or_else(|e| panic!("write input fixture {input_path:?}: {e}"));
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the directory is writable before writing fixtures
assert!(tmp.path().is_dir() && !tmp.path().is_file());

Try / catch

// Include path and OS error in the failure
std::fs::write(&input_path, "b\na\n")
    .unwrap_or_else(|e| panic!("write fixture {input_path:?}: {e}"));

Prevention

When it happens

Trigger: The temp dir from line 8235 was dropped early or is unwritable; the path contains invalid characters; the filesystem is full or read-only when the test runs.

Common situations: Read-only CI mounts, a fixture path colliding with an existing directory, or tmp being consumed/moved before the write.

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/fb86d394f7fa926b. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/tests.rs:8237

            let output = registry
                .execute("agent_read_only_e2e", "bash", input)
                .await
                .unwrap_or_else(|error| {
                    panic!("{role:?} concrete executor must run {command}: {error}")
                });
            assert!(!output.trim().is_empty(), "{role:?} {command}");
        }
    }
}

/// Read-only text filters may transform stdout, but they must not reach their
/// file-output or helper-program forms through the same bounded bash carve-out.
#[tokio::test]
async fn read_only_inspection_roles_cannot_write_through_text_filters() {
    for role in [FleetRole::Scout, FleetRole::Reviewer, FleetRole::Planner] {
        let tmp = tempdir().expect("tempdir");
        let input_path = tmp.path().join("input.txt");
        std::fs::write(&input_path, "b\na\n").expect("input fixture");
        let output_path = tmp.path().join("filter-output.txt");
        let mut runtime =
            stub_runtime().with_agent_tool_surface_options(enabled_agent_surface_options());
        runtime.context = ToolContext::new(tmp.path().to_path_buf());
        runtime.worker_profile = WorkerRuntimeProfile::for_role(role.clone());
        seed_read_only_role_deny_list(&mut runtime);
        let registry = SubAgentToolRegistry::new(
            runtime,
            role.clone(),
            None,
            crate::tools::todo::new_shared_todo_list(),
            crate::tools::plan::new_shared_plan_state(),
        );

        let call = json!({"command": "sort -o filter-output.txt input.txt"});
        let envelope_refusal = registry
            .envelope_refusal("bash", &call)
            .expect("the envelope must independently refuse the write-capable filter");

View on GitHub (pinned to 433685b202)