Hmbown/CodeWhale · error · anyhow::Error
failed to open
Error message
failed to open {} What it means
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).
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.
Example fix
// before sudo ./codewhale # creates telemetry files owned by root // after sudo chown -R $USER ~/.local/share/codewhale/telemetry
Defensive patterns
Strategy: try-catch
Validate before calling
let p = telemetry::tombstone_path(root);
let meta = std::fs::metadata(&p);
let precheck_ok = match &meta {
Ok(m) => m.is_file() && !m.permissions().readonly(),
Err(e) => e.kind() == std::io::ErrorKind::NotFound,
}; Try / catch
match arm_or_wipe() {
Ok(v) => v,
Err(e) if e.to_string().contains("failed to open") => {
// log path from message, fix perms or delete stale tombstone, retry once
}
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- could not inspect
- could not inspect
- could not read
- {error}
- external credential path must name a regular file
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d0c5d39276f16290.
Report an issue: GitHub.
Appendix: source
Thrown at crates/telemetry/src/buffer.rs:114
///
/// Re-checked on **every** append and immediately before **every** send. This is
/// what makes `codewhale config set telemetry false` — an external write by
/// another process — observable to a session that is already running.
#[must_use]
pub fn tombstone_present(root: &Path) -> bool {
tombstone_path(root).exists()
}
/// Read the exact tombstone generation, or `None` when collection has never
/// been disabled in this home.
pub(crate) fn tombstone_generation(root: &Path) -> Result<Option<TombstoneGeneration>> {
let path = tombstone_path(root);
let file = match File::open(&path) {
Ok(file) => file,
Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(error) => {
return Err(
anyhow::Error::new(error).context(format!("failed to open {}", path.display()))
);
}
};
let mut bytes = Vec::new();
file.take(MAX_TOMBSTONE_BYTES + 1)
.read_to_end(&mut bytes)
.with_context(|| format!("failed to read {}", path.display()))?;
if bytes.len() as u64 > MAX_TOMBSTONE_BYTES {
anyhow::bail!("{} exceeds the tombstone size limit", path.display());
}
Ok(Some(TombstoneGeneration(bytes)))
}
/// Create the telemetry directory `0700`, if it is missing.
pub fn ensure_dir(root: &Path) -> Result<()> {
if root.is_dir() {
return Ok(());
}View on GitHub (pinned to 73e0f67d83)