Hmbown/CodeWhale · error

workspace .env FIFO blocked startup

Error message

workspace .env FIFO blocked startup: {timeout}

What it means

A test-timeout panic inside a workspace .env loading test. The test creates a FIFO (named pipe) where a real .env file would be, starts the loader in a worker thread, and expects the loader to fail fast with 'not a regular file'. If the loader instead blocks on reading the FIFO, the receiver times out after 1 second and the test panics with 'workspace .env FIFO blocked startup: {timeout}', which also opens a writer to unblock and join the worker.

Solutions

  1. Restore an explicit regular-file validation (fs::metadata + is_file) in the workspace .env loader before opening the file.
  2. Ensure the loader rejects non-regular files with an error containing 'not a regular file' rather than attempting to read.
  3. If the failure is a flaky timeout on slow machines, raise the recv_timeout budget or the Duration used in the panic message.
  4. Re-run the single test to confirm the loader now fails fast on FIFOs.

Example fix

// before
let contents = std::fs::read_to_string(&dotenv)?;
// after
let meta = std::fs::metadata(&dotenv)?;
if !meta.is_file() {
    return Err(anyhow!("workspace .env is not a regular file"));
}
let contents = std::fs::read_to_string(&dotenv)?;
Defensive patterns

Strategy: validation

Validate before calling

let meta = std::fs::metadata(&dotenv_path).ok()?;
if !meta.is_file() {
    return Err("workspace .env is not a regular file");
}

Type guard

fn is_regular_file(p: &std::path::Path) -> bool {
    std::fs::metadata(p).map(|m| m.is_file()).unwrap_or(false)
}

Try / catch

match std::fs::metadata(&dotenv) {
    Ok(m) if m.is_file() => load_dotenv(&dotenv),
    _ => return Err(anyhow!("workspace .env is not a regular file")),
}

Prevention

When it happens

Trigger: The .env loader blocks reading a FIFO instead of rejecting it; rx.recv_timeout(1s) elapses without the expected error being sent, hitting the panic in the timeout arm.

Common situations: A developer replaces the regular-file check (metadata().is_file()) with a streaming read; a regression lets startup hang on a FIFO or device file placed at the workspace .env path; slow CI makes the 1-second timeout too tight.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/2ceb0d0b91b90db1. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:17682

        let worker = std::thread::spawn(move || {
            let result = load_workspace_dotenv_credentials_from_path(&worker_path)
                .map(|_| "unexpected success".to_string())
                .unwrap_or_else(|error| error.to_string());
            tx.send(result).expect("send loader result");
        });

        let error = match rx.recv_timeout(Duration::from_secs(1)) {
            Ok(error) => error,
            Err(timeout) => {
                // Release a regressed blocking reader so the test can fail
                // promptly instead of leaving a stuck process behind.
                let _writer = std::fs::OpenOptions::new()
                    .write(true)
                    .open(&dotenv)
                    .expect("open fifo writer to release blocked reader");
                let _ = rx.recv_timeout(Duration::from_secs(1));
                worker.join().expect("join released loader");
                panic!("workspace .env FIFO blocked startup: {timeout}");
            }
        };
        worker.join().expect("join loader");

        assert!(error.contains("not a regular file"), "{error}");
    }

    #[test]
    fn exec_json_conflicts_with_stream_json_output() {
        let err = Cli::try_parse_from([
            "codewhale",
            "exec",
            "--json",
            "--output-format",
            "stream-json",
            "hello",
        ])
        .expect_err("json summary and stream-json must not mix");

View on GitHub (pinned to 433685b202)