Hmbown/CodeWhale · error
provider catalog lock
Error message
provider catalog lock {} must be a regular file What it means
The provider catalog's on-disk cache uses a lock file with advisory locking. Before locking, `open_cache_lock` verifies the path is a regular file; if it is a directory, FIFO, socket, or device node, locking semantics are unsafe and the operation fails loudly rather than silently misbehaving.
Solutions
- Inspect the path shown in the message with `ls -la` and remove/replace the non-regular entry (e.g. `rm -rf <lock-path>` if it is a directory).
- Restart the operation; the lock file is recreated as a regular file.
- Check that no container volume or sync tool is mounted at that path.
- If it recurs, clear the whole provider-catalog cache directory.
Example fix
// before: lock path is a directory $ ls -la ~/.cache/codewhale/provider-catalog.lock drwxr-xr-x provider-catalog.lock // after $ rm -rf ~/.cache/codewhale/provider-catalog.lock $ codewhale # lock recreated as a regular file
Defensive patterns
Strategy: validation
Validate before calling
import stat from 'node:fs';
const st = stat.statSync(lockPath);
if (!st.isFile()) {
console.error(`${lockPath} is not a regular file — remove it before running`);
process.exit(1);
} Type guard
const isRegularFile = (p) => { try { return require('fs').statSync(p).isFile(); } catch { return false; } }; Try / catch
try {
await codewhale.providers.refresh();
} catch (e) {
if (e.message.includes('must be a regular file')) {
fs.rmSync(lockPath, { recursive: true, force: true });
return codewhale.providers.refresh();
}
throw e;
} Prevention
- Don't mount volumes or point caches at paths where tools create directories.
- Exclude the codewhale cache dir from dotfile sync and snapshot tools.
- After crashes, check the cache dir for stray directories before retrying.
When it happens
Trigger: `open_cache_lock` (called by `load_from_disk`, `persist_scope`, `persist_failure_scope`) opens the lock path and `metadata.is_file()` is false — e.g. something created a directory at the lock file's path.
Common situations: A previous crash or bad tooling created a directory named like the lock file, a container/tmpfs volume mounted at that path, dotfile-sync tools replacing the lock with a symlink/dir, or permission-restricted paths resolving oddly.
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
- bounded fragment module missing required marker
- catalog cache unavailable
- event transaction runs once
- provider catalog lock
- saved cache route identity
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b211ef9c31183ef1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/provider_catalog_live.rs:537
#[cfg(unix)]
{
use std::os::unix::fs::OpenOptionsExt as _;
options
.mode(0o600)
.custom_flags(libc::O_NOFOLLOW | libc::O_CLOEXEC | libc::O_NONBLOCK);
}
#[cfg(windows)]
{
use std::os::windows::fs::OpenOptionsExt as _;
options.custom_flags(0x0020_0000); // FILE_FLAG_OPEN_REPARSE_POINT
}
let file = options
.open(path)
.with_context(|| format!("open provider catalog lock {}", path.display()))?;
let metadata = file
.metadata()
.with_context(|| format!("inspect provider catalog lock {}", path.display()))?;
anyhow::ensure!(
metadata.is_file(),
"provider catalog lock {} must be a regular file",
path.display()
);
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt as _;
anyhow::ensure!(
metadata.nlink() == 1,
"provider catalog lock {} must not be hard linked",
path.display()
);
}
#[cfg(windows)]
{
use std::os::windows::fs::MetadataExt as _;
const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x0000_0400;
anyhow::ensure!(View on GitHub (pinned to 73e0f67d83)