Hmbown/CodeWhale · error · anyhow::Error

{} is not a regular file

Error message

{} is not a regular file

What it means

read_stable_workspace_dotenv opens the workspace .env without following symlinks and immediately checks the fstat metadata of what it opened. If the entry is not a regular file — a FIFO, socket, device, or directory — the load is refused: only a plain regular file is an acceptable workspace-owned credential source, because non-regular files can block, stream, or masquerade.

Source

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

        }
        if ch == '#' && !double_quoted {
            comment = true;
            continue;
        }
        if ch == '$' {
            return true;
        }
    }
    false
}

fn read_stable_workspace_dotenv(path: &Path) -> Result<Vec<u8>> {
    let mut file = open_workspace_dotenv_without_following_links(path)?;
    let metadata = file
        .metadata()
        .map_err(|error| anyhow!("could not inspect {}: {error}", path.display()))?;
    if !metadata.is_file() {
        bail!("{} is not a regular file", path.display());
    }
    if workspace_dotenv_has_multiple_links(&file, &metadata)? {
        bail!(
            "{} has multiple filesystem links, not a unique workspace-owned file",
            path.display()
        );
    }
    if metadata.len() > MAX_WORKSPACE_DOTENV_BYTES {
        bail!(
            "{} exceeds the {} byte workspace .env limit",
            path.display(),
            MAX_WORKSPACE_DOTENV_BYTES
        );
    }

    let mut contents = Vec::with_capacity(metadata.len() as usize);
    (&mut file)
        .take(MAX_WORKSPACE_DOTENV_BYTES + 1)

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Inspect the entry: `ls -l .env` must start with `-`; recreate it as a regular file
  2. If a tool created the non-regular entry, stop that tool from managing workspace .env
  3. Regenerate .env with an editor or a plain write rather than special filesystem objects

Example fix

# before
ls -l .env        # prw-r--r-- .env   (named pipe)

# after
rm .env && printf 'KEY=value\n' > .env
ls -l .env        # -rw-r--r-- .env
Defensive patterns

Strategy: validation

Validate before calling

# .env must be a regular file
[ -f .env ] && [ ! -L .env ] || { echo '.env missing or not a regular file'; exit 2; }
[ "$(stat -c '%F' .env 2>/dev/null)" = 'regular file' ] || { echo '.env is not a regular file'; exit 2; }

Type guard

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

Prevention

When it happens

Trigger: Workspace .env replaced by a named pipe (mkfifo) or device entry; the entry swapped for a non-regular file between open and fstat; unusual filesystems where the no-follow open lands on a non-regular object.

Common situations: Pranks or probing with a FIFO .env to hang or inject into credential loading; broken sync tools materializing .env as something other than a file; container mounts that present .env as a special file.

Related errors


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