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(¤t) == 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
- Inspect the hook file at the printed path and remove it manually if it is truly not needed: `rm <path-to>/pre-push`
- Back up the hook content, remove the file, re-run uninstall, then re-create your custom hook
- Reinstall the Flow hook (`push hooks install --force`) then uninstall, if the hook is actually Flow's but the marker was edited out
- 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
- Run the tool's hook status command before install/uninstall to see if the hook is Flow-managed
- Don't hand-edit the generated pre-push hook; the marker comment is Flow's ownership check
- Migrate other hook managers (husky/pre-commit) off the same core.hooksPath before using this tool
- Back up custom hook scripts before touching hooks
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
- jj git export retry loop should always return
- refusing doc commit because unrelated changes are present: {
- {} is not inside a git repository
- derived shared repo root {} does not contain .git
- Lin.app is not running
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/37e1b2acce3fbab2.
Report an issue: GitHub.