rtk-ai/rtk · error
Failed to uninstall RTK from one or more Droid hook files
Error message
Failed to uninstall RTK from one or more Droid hook files:
- {} What it means
During `rtk init` uninstall, RTK tries to remove its hooks from every known Droid hook file. If removal from any candidate file fails, all per-file errors are collected and returned together as this aggregated anyhow error.
Solutions
- Read the per-file messages after the header to see which files failed and why.
- Fix permissions on the listed files (chown/chmod) and re-run the uninstall.
- Manually remove the RTK hook entries from the failing JSON hook files if automated removal keeps failing.
- Restore the hook files to a valid state (reinstall/reconfigure Droid) and retry.
Example fix
// before $ rtk init --uninstall # fails: permission denied // after chmod u+w ~/.droid/hooks.json && rtk init --uninstall
Defensive patterns
Strategy: try-catch
Validate before calling
import json, os
for p in ['~/.droid/hooks.json']:
path = os.path.expanduser(p)
if not os.access(path, os.W_OK):
raise PermissionError(f'{path} is not writable')
json.load(open(path)) # must be valid JSON for hook removal Try / catch
match rtk_uninstall_droid() {
Err(e) if e.to_string().starts_with("Failed to uninstall RTK from one or more Droid hook files") => {
// parse per-file errors, fix permissions/JSON, retry
}
other => other,
} Prevention
- Keep Droid hook files writable by your user and valid JSON
- Do not hand-edit hook files while rtk owns entries
- Back up hook files before running uninstall
When it happens
Trigger: Running the Droid uninstall path when one or more hook files cannot be processed: unreadable file, permission denied on write, malformed JSON that prevents hook removal, or the file path being a directory/symlink target that is missing.
Common situations: Hook files owned by another user or made read-only; partial/corrupt Droid config after a failed upgrade; files manually edited so the RTK hook JSON no longer matches what uninstall expects.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- at could not be read; leaving it alone.
- Cursor uninstall only works with --global flag
- hook stdin exceeds byte limit
- Invalid hash format in
- Invalid SHA-256 hash in
AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19).
Data as JSON: /api/errors/5b04db12cb259e4f.
Report an issue: GitHub.
Appendix: source
Thrown at src/hooks/init.rs:3745
}
Ok(())
}
fn uninstall_droid_at(droid_dir: &Path, ctx: InitContext) -> Result<Vec<String>> {
let mut removed = Vec::new();
let mut errors = Vec::new();
for candidate in droid_hook_file_candidates(droid_dir) {
match remove_droid_hook_from_file(&candidate, ctx) {
Ok(true) => {
removed.push(format!("Droid hook file: {}", candidate.path.display()));
}
Ok(false) => {}
Err(error) => errors.push(format!("{}: {error:#}", candidate.path.display())),
}
}
if !errors.is_empty() {
return Err(anyhow::anyhow!(
"Failed to uninstall RTK from one or more Droid hook files:\n - {}",
errors.join("\n - ")
));
}
Ok(removed)
}
/// Strip the RTK entry from one Droid hook file. Returns true if the file
/// held an RTK entry (and was rewritten, unless dry-run).
fn remove_droid_hook_from_file(file: &DroidHookFile, ctx: InitContext) -> Result<bool> {
let InitContext {
verbose, dry_run, ..
} = ctx;
let path = &file.path;
let mut root = match read_json_file(path)? {
Some(v) => v,View on GitHub (pinned to 0924356b4c)