nikivdev/code · error

Refusing to overwrite non-Flow hook at {}. Re-run with `f pu

Error message

Refusing to overwrite non-Flow hook at {}.
Re-run with `f push hooks install --force` to replace it.

What it means

Raised by install_hooks in src/push_hook.rs when a pre-push file already exists at the target hook path but does not contain the Flow marker (flow-global-pre-push-hook-v1), and --force was not passed. This protects a user's hand-written or third-party pre-push hook from being silently replaced by the Flow script.

Source

Thrown at src/push_hook.rs:88

pub fn install_hooks(force: bool) -> Result<()> {
    let hooks_path = push_policy::effective_global_hooks_path()?;
    let current_hooks_path = current_global_hooks_path()?;

    if let Some(current) = current_hooks_path.as_ref()
        && normalize_path(current) != normalize_path(&hooks_path)
        && !force
    {
        bail!(
            "Global core.hooksPath already points to {}.\nRe-run with `f push hooks install --force` to overwrite it.",
            current.display()
        );
    }

    fs::create_dir_all(&hooks_path)
        .with_context(|| format!("failed to create {}", hooks_path.display()))?;
    let hook_path = hooks_path.join("pre-push");
    if hook_path.exists() && !is_flow_managed_hook(&hook_path)? && !force {
        bail!(
            "Refusing to overwrite non-Flow hook at {}.\nRe-run with `f push hooks install --force` to replace it.",
            hook_path.display()
        );
    }

    fs::write(&hook_path, render_pre_push_hook_script())
        .with_context(|| format!("failed to write {}", hook_path.display()))?;
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let mut perms = fs::metadata(&hook_path)?.permissions();
        perms.set_mode(0o755);
        fs::set_permissions(&hook_path, perms)?;
    }

    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());

View on GitHub (pinned to a747e741ae)

Solutions

  1. If replacement is intended, re-run with `f push hooks install --force`
  2. Back up the existing hook (e.g. `mv pre-push pre-push.bak`) and merge its logic into your workflow, then install
  3. Check the file contents to confirm whether it is still needed before forcing an overwrite

Example fix

// before
$ f push hooks install
Refusing to overwrite non-Flow hook at ~/.flow/hooks/pre-push.
// after
$ cp ~/.flow/hooks/pre-push ~/.flow/hooks/pre-push.bak
$ f push hooks install --force
Defensive patterns

Strategy: validation

Validate before calling

let hook = hooks_dir.join("pre-push");
if hook.exists() {
    let content = std::fs::read_to_string(&hook)?;
    if !content.contains("flow-global-pre-push-hook-v1") {
        eprintln!("existing non-Flow pre-push hook at {}; back it up, then use --force", hook.display());
    }
}

Try / catch

match result {
    Err(e) if e.to_string().contains("Refusing to overwrite non-Flow hook") => {
        eprintln!("back up the hook, merge logic, then re-run with --force");
    }
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: Running `f push hooks install` when <hooks_path>/pre-push exists, is_flow_managed_hook returns false (no Flow marker in the file contents), and force is false.

Common situations: A custom pre-push script or another tool's hook (pre-commit framework, husky) already occupies the file; a partially edited Flow hook lost its marker line; reinstalling after switching hook managers.

Related errors


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