nikivdev/code · error

Refusing to commit internal .ai files

Error message

Refusing to commit internal .ai files

What it means

Before committing, the tool inspects staged files (git diff --cached --name-only) and refuses to commit if any internal .ai working files are staged. These are tool-internal files that should not enter project history. The error lists the offending paths and can be bypassed with FLOW_ALLOW_INTERNAL_COMMIT=1.

Source

Thrown at src/commit.rs:6612

    setup::add_gitignore_entry(repo_root, ".ai/internal/")?;
    Ok(())
}

fn ensure_no_internal_staged(repo_root: &Path) -> Result<()> {
    if env::var("FLOW_ALLOW_INTERNAL_COMMIT").as_deref() == Ok("1") {
        return Ok(());
    }
    let staged = internal_staged_paths(repo_root);
    if staged.is_empty() {
        return Ok(());
    }

    println!("Refusing to commit internal .ai files:");
    for path in staged {
        println!("  - {}", path);
    }
    println!("Remove these from staging or set FLOW_ALLOW_INTERNAL_COMMIT=1 to override.");
    bail!("Refusing to commit internal .ai files");
}

fn internal_staged_paths(repo_root: &Path) -> Vec<String> {
    let output = Command::new("git")
        .args(["diff", "--cached", "--name-only"])
        .current_dir(repo_root)
        .output();

    let Ok(output) = output else {
        return Vec::new();
    };
    if !output.status.success() {
        return Vec::new();
    }

    let files = String::from_utf8_lossy(&output.stdout);
    files
        .lines()

View on GitHub (pinned to a747e741ae)

Solutions

  1. Unstage the listed files: `git restore --staged <path>` (or `git rm --cached -r .ai/`)
  2. Add the .ai directory to .gitignore so it never gets staged
  3. Run `git add` with explicit paths instead of `git add .`
  4. Set FLOW_ALLOW_INTERNAL_COMMIT=1 to deliberately override, only if you truly want these files committed

Example fix

// before (shell)
git add . && f commit -m "msg"   # stages .ai/* too
// after (shell)
printf '.ai/\n' >> .gitignore && git restore --staged .ai && f commit -m "msg"
Defensive patterns

Strategy: validation

Validate before calling

let staged = Command::new("git")
    .args(["diff", "--cached", "--name-only"])
    .output()?;
let names = String::from_utf8_lossy(&staged.stdout);
let internal: Vec<&str> = names.lines()
    .filter(|p| p.starts_with(".ai/")).collect();
if !internal.is_empty() {
    eprintln!("unstage first: {}", internal.join(", "));
}

Try / catch

if let Err(e) = tool.commit(msg) {
    if e.to_string().contains("internal .ai files") {
        let _ = Command::new("git").args(["restore", "--staged", ".ai"]).status();
        tool.commit(msg)?;
    } else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: Running `f commit` while internal .ai files (e.g. commit queue/review state under .ai/) are in the git staging area, as detected by internal_staged_paths().

Common situations: User ran `git add .` or `git add -A` after the tool wrote its internal state files, .gitignore is missing entries for the .ai directory, or a previous crashed run left state files behind that then got staged.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/39727277c8caea12. Report an issue: GitHub.