nikivdev/code · error

Refusing to remove non-Flow hook at {}.

Error message

Refusing to remove non-Flow hook at {}.

What it means

`uninstall_hooks` refuses to delete a pre-push hook file that exists but does not contain the Flow marker (`is_flow_managed_hook` checks for FLOW_PRE_PUSH_HOOK_MARKER). The library deliberately avoids destroying hook files it did not create, since they may belong to other tools or hand-written scripts.

Source

Thrown at src/push_hook.rs:120

    }

    git_config_global_set("core.hooksPath", &hooks_path)?;
    println!("Installed Flow pre-push hook at {}", hook_path.display());
    println!("Global core.hooksPath -> {}", hooks_path.display());
    Ok(())
}

pub fn uninstall_hooks() -> Result<()> {
    let hooks_path = push_policy::effective_global_hooks_path()?;
    let hook_path = hooks_path.join("pre-push");
    let current_hooks_path = current_global_hooks_path()?;

    if hook_path.exists() && is_flow_managed_hook(&hook_path)? {
        fs::remove_file(&hook_path)
            .with_context(|| format!("failed to remove {}", hook_path.display()))?;
        println!("Removed Flow pre-push hook at {}", hook_path.display());
    } else if hook_path.exists() {
        bail!(
            "Refusing to remove non-Flow hook at {}.",
            hook_path.display()
        );
    } else {
        println!("No Flow pre-push hook found at {}", hook_path.display());
    }

    if let Some(current) = current_hooks_path
        && normalize_path(&current) == normalize_path(&hooks_path)
    {
        git_config_global_unset("core.hooksPath")?;
        println!("Unset global core.hooksPath");
    }

    Ok(())
}

pub fn print_hook_status() -> Result<()> {

View on GitHub (pinned to a747e741ae)

Solutions

  1. Inspect the hook file at the printed path and remove it manually if it is truly not needed: `rm <path-to>/pre-push`
  2. Back up the hook content, remove the file, re-run uninstall, then re-create your custom hook
  3. Reinstall the Flow hook (`push hooks install --force`) then uninstall, if the hook is actually Flow's but the marker was edited out
  4. Point git's core.hooksPath elsewhere with `git config --global --unset core.hooksPath` and manage hooks independently

Example fix

// before (manual removal)
$ f push hooks uninstall
Error: Refusing to remove non-Flow hook at /home/user/.flow/hooks/pre-push.
// after
$ grep -v FLOW /home/user/.flow/hooks/pre-push  # inspect: it's a husky script
$ rm /home/user/.flow/hooks/pre-push
$ f push hooks uninstall  # now reports 'No Flow pre-push hook found'
Defensive patterns

Strategy: validation

Validate before calling

// preflight: only uninstall if the hook is Flow-managed
use std::fs;
fn flow_managed(hook: &std::path::Path, marker: &str) -> anyhow::Result<bool> {
    Ok(hook.exists() && fs::read_to_string(hook)?.contains(marker))
}
if !flow_managed(&hook_path, FLOW_PRE_PUSH_HOOK_MARKER)? {
    eprintln!("skipping uninstall: {} is not Flow-managed", hook_path.display());
}

Type guard

fn is_flow_managed(hook: &std::path::Path, marker: &str) -> bool {
    std::fs::read_to_string(hook).map(|c| c.contains(marker)).unwrap_or(false)
}

Try / catch

match uninstall_hooks() {
    Ok(()) => {},
    Err(e) if e.to_string().contains("Refusing to remove non-Flow hook") => {
        eprintln!("hook not managed by Flow; remove manually if desired");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Running `uninstall_hooks` (via `run_hooks_command` uninstall) when `<hooks>/pre-push` exists but was authored by something else — e.g. installed by husky, pre-commit, or manually — so its content lacks the Flow marker.

Common situations: Previously used husky or the `pre-commit` framework; another tool rewrote or replaced the hook after Flow installed it; a developer hand-edited the hook and removed the marker comment; switching hook managers on the same machine.

Related errors


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