Hmbown/CodeWhale · error

sub-agent state path must be a regular file: {}

Error message

sub-agent state path must be a regular file: {}

What it means

`read_subagent_state_file` lstats the path and requires a regular, non-symlink file before opening; reading through symlinks, fifos, sockets, or directories is refused. This pairs with the symlink-traversal guard so state reads cannot be redirected or blocked on special files.

Source

Thrown at crates/tui/src/tools/subagent/mod.rs:7762

            continue;
        };
        if metadata.file_type().is_symlink() {
            return Err(anyhow!(
                "sub-agent state path must not traverse symlinks: {}",
                current.display()
            ));
        }
    }
    Ok(())
}

fn read_subagent_state_file(state_root: &Path, path: &Path) -> Result<String> {
    let state_root = normalize_subagent_workspace(state_root);
    reject_root_relative_symlinks(&state_root, path)?;
    let metadata = fs::symlink_metadata(path)?;
    let file_type = metadata.file_type();
    if file_type.is_symlink() || !file_type.is_file() {
        return Err(anyhow!(
            "sub-agent state path must be a regular file: {}",
            path.display()
        ));
    }

    let mut file = open_subagent_state_file(path)?;
    let mut raw = String::new();
    file.read_to_string(&mut raw)?;
    Ok(raw)
}

#[cfg(unix)]
fn open_subagent_state_file(path: &Path) -> Result<fs::File> {
    use std::os::unix::fs::OpenOptionsExt;

    fs::OpenOptions::new()
        .read(true)
        .custom_flags(libc::O_NOFOLLOW)

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Inspect the path with ls -l; remove any symlink or special file and restore a regular file (or let the manager recreate it).
  2. Never link state files — keep them as regular files inside the state root.
  3. If a directory occupies the path, move it and retry.
Defensive patterns

Strategy: validation

Validate before calling

let meta = std::fs::symlink_metadata(&path)?;
if meta.file_type().is_symlink() || !meta.file_type().is_file() {
    // not readable as state: replace with a regular file before calling
}

Type guard

fn is_regular_non_symlink(meta: &std::fs::Metadata) -> bool {
    !meta.file_type().is_symlink() && meta.file_type().is_file()
}

Try / catch

match read_subagent_state_file(&state_root, &path) {
    Err(e) if e.to_string().contains("must be a regular file") => { /* remove symlink/fifo, restore file, retry */ }
    r => r?,
}

Prevention

When it happens

Trigger: The state path is a symlink to a file elsewhere, a named pipe a process is holding, or a directory at the expected file location.

Common situations: Symlinked state files (manual shortcuts, tooling); a hung writer leaving a fifo; path collisions where a directory was created at the file's path.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/7992441cba790a83. Report an issue: GitHub.