{"record":{"id":"d0c5d39276f16290","repo":"Hmbown/CodeWhale","slug":"failed-to-open","errorCode":null,"errorMessage":"failed to open {}","messagePattern":"failed to open (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/telemetry/src/buffer.rs","lineNumber":114,"sourceCode":"///\n/// Re-checked on **every** append and immediately before **every** send. This is\n/// what makes `codewhale config set telemetry false` — an external write by\n/// another process — observable to a session that is already running.\n#[must_use]\npub fn tombstone_present(root: &Path) -> bool {\n    tombstone_path(root).exists()\n}\n\n/// Read the exact tombstone generation, or `None` when collection has never\n/// been disabled in this home.\npub(crate) fn tombstone_generation(root: &Path) -> Result<Option<TombstoneGeneration>> {\n    let path = tombstone_path(root);\n    let file = match File::open(&path) {\n        Ok(file) => file,\n        Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None),\n        Err(error) => {\n            return Err(\n                anyhow::Error::new(error).context(format!(\"failed to open {}\", path.display()))\n            );\n        }\n    };\n    let mut bytes = Vec::new();\n    file.take(MAX_TOMBSTONE_BYTES + 1)\n        .read_to_end(&mut bytes)\n        .with_context(|| format!(\"failed to read {}\", path.display()))?;\n    if bytes.len() as u64 > MAX_TOMBSTONE_BYTES {\n        anyhow::bail!(\"{} exceeds the tombstone size limit\", path.display());\n    }\n    Ok(Some(TombstoneGeneration(bytes)))\n}\n\n/// Create the telemetry directory `0700`, if it is missing.\npub fn ensure_dir(root: &Path) -> Result<()> {\n    if root.is_dir() {\n        return Ok(());\n    }","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/telemetry/src/buffer.rs#L96-L132","documentation":"The telemetry buffer failed to open the tombstone file at its expected path. NotFound is treated as a normal 'no tombstone' outcome (returns Ok(None)); any other open error (permissions, is-a-directory, I/O failure) is wrapped in anyhow with the path in the context message during tombstone reading (called by wipe and arm).","triggerScenarios":"Calling `wipe` or `arm` when the tombstone file exists at `tombstone_path(root)` but cannot be opened: permission denied, path is a directory, stale symlink, or underlying I/O error.","commonSituations":"Telemetry data directory owned by a different user after running as root once; a directory accidentally created where the tombstone file should be; NFS/overlay filesystem returning EIO; read-only mount after crash recovery.","solutions":["Check permissions on the tombstone file and its parent directory (`ls -la` the path printed in the message) and chown/chmod to the running user.","If a directory occupies the tombstone path, remove it so the file can be recreated.","Verify the filesystem is writable and not remounted read-only (`mount | grep <path>`).","As a last resort, delete the corrupted tombstone file; NotFound is handled gracefully and state will be rebuilt."],"exampleFix":"// before\nsudo ./codewhale  # creates telemetry files owned by root\n\n// after\nsudo chown -R $USER ~/.local/share/codewhale/telemetry","handlingStrategy":"try-catch","validationCode":"let p = telemetry::tombstone_path(root);\nlet meta = std::fs::metadata(&p);\nlet precheck_ok = match &meta {\n    Ok(m) => m.is_file() && !m.permissions().readonly(),\n    Err(e) => e.kind() == std::io::ErrorKind::NotFound,\n};","typeGuard":null,"tryCatchPattern":"match arm_or_wipe() {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"failed to open\") => {\n        // log path from message, fix perms or delete stale tombstone, retry once\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Don't run the app as root if you later run it as a normal user; keep one owner for the telemetry dir.","Monitor for directories accidentally created at tombstone_path.","Check filesystem writability/mount state after crash recovery."],"tags":["filesystem","telemetry","io"],"backgroundTag":"file-open-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}