{"record":{"id":"caa10f240c9456c2","repo":"rtk-ai/rtk","slug":"at-could-not-be-read-leaving-it-alone","errorCode":null,"errorMessage":"{} at {} could not be read; leaving it alone.","messagePattern":"(.+?) at (.+?) could not be read; leaving it alone\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/hooks/init.rs","lineNumber":4320,"sourceCode":"    match fs::read_to_string(path) {\n        Ok(content) => Ok(Some(content)),\n        Err(error) => {\n            eprintln!(\n                \"[warn] {} at {} could not be read; leaving it alone: {}\",\n                name,\n                path.display(),\n                error\n            );\n            if ctx.dry_run {\n                println!(\n                    \"[dry-run] would leave unreadable {} unchanged: {}\",\n                    name,\n                    path.display()\n                );\n                print_dry_run_footer();\n                Ok(None)\n            } else {\n                anyhow::bail!(\n                    \"{} at {} could not be read; leaving it alone.\",\n                    name,\n                    path.display()\n                );\n            }\n        }\n    }\n}\n\n/// Uninstall Pi extension for the given scope.\n/// Mirrors `uninstall_codex` / `uninstall_hermes`: extracted from the dispatcher\n/// so it can be tested and reasoned about independently.\nfn uninstall_pi_with_patch_mode(\n    global: bool,\n    patch_mode: PatchMode,\n    ctx: InitContext,\n) -> Result<()> {\n    let InitContext {","sourceCodeStart":4302,"sourceCodeEnd":4338,"githubUrl":"https://github.com/rtk-ai/rtk/blob/0924356b4caba4989607227b7c8824d3d8098719/src/hooks/init.rs#L4302-L4338","documentation":"During `rtk init` uninstall/cleanup of the Pi extension, rtk checks whether the existing plugin file contains RTK content to decide if it is safe to remove. If the file exists but cannot be read (permissions, IO error, symlink issues), rtk refuses to guess and aborts with this bail instead of deleting or modifying an unreadable file. This is a deliberate safety guard: never remove a file whose ownership is unknown.","triggerScenarios":"Running `rtk init` (Pi mode uninstall/patch flow) when the Pi extension file at the target path exists but `std::fs::read_to_string` fails — e.g. file has no read permission, is owned by another user, sits on a failing mount, or an IO error occurs mid-read.","commonSituations":"Plugin file created by root or another user while rtk runs unprivileged; restrictive umask or corporate-managed dotfiles; network/overlay filesystem hiccup in a container or NFS home directory.","solutions":["Check file permissions with `ls -l <path>` and fix them (e.g. `chmod u+r <path>`) or run rtk with sufficient privileges.","Manually inspect and remove the file yourself (`rm <path>` or back it up), then rerun `rtk init`.","Use `rtk init --dry-run` to see which path is affected before retrying.","If the file is on a flaky mount, remount or copy it to a local disk and retry."],"exampleFix":"// before (shell)\nrtk init   # fails: could not be read\n# after (shell)\nchmod u+r ~/.pi/extensions/rtk.ts && rtk init","handlingStrategy":"fallback","validationCode":"path=$(ls ~/.pi/extensions/rtk.* 2>/dev/null | head -1)\nif [ -n \"$path\" ] && [ ! -r \"$path\" ]; then\n  echo \"Cannot read $path — fix permissions before running rtk init\"\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":"rtk init || { echo 'rtk init failed; run with --dry-run to inspect the affected file' >&2; exit 1; }","preventionTips":["Run rtk init as the same user that owns the agent config directory.","Check `ls -l` on agent extension files before uninstalling.","Prefer `--dry-run` first to spot unreadable paths safely."],"tags":["file-io","permissions","uninstall","init"],"backgroundTag":"file-read-failed","analyzedSha":"0924356b4caba4989607227b7c8824d3d8098719","analyzedAt":"2026-09-19T19:25:29.612Z","contentChangedAt":"2026-09-19T19:25:29.612Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}