Hmbown/CodeWhale · error
refusing non-regular or reparse-point config lock at
Error message
refusing non-regular or reparse-point config lock at {} What it means
Windows-only safety check in validate_windows_lock_handle (part of the config write-lock path). Before using the lock file handle, its metadata is inspected: if the path is not a regular file or carries the FILE_ATTRIBUTE_REPARSE_POINT flag (symlink/junction/mount point), the lock is refused to prevent lock-file redirection attacks or locking an unintended target.
Solutions
- Remove the symlink/junction at the lock path so a real regular file can be created there.
- Move the config out of a cloud-synced directory or exclude it from sync placeholders.
- Point the config directory at a local path instead of a symlinked/junctioned location.
- Verify with `dir /AL` (or `fsutil reparsepoint query`) that the lock path is no longer a reparse point, then retry.
Example fix
// before (lock path is a symlink) C:\Users\me\.codewhale\config.lock -> D:\sync\config.lock // after (regular file, no reparse point) fsutil reparsepoint delete C:\Users\me\.codewhale\config.lock del C:\Users\me\.codewhale\config.lock # recreated as a real file on next run
Defensive patterns
Strategy: validation
Validate before calling
// PowerShell: ensure the config lock path is a regular file, not a reparse point
$lock = "$env:USERPROFILE\.codewhale\config.lock"
if (Test-Path $lock) {
$item = Get-Item $lock -Force
if ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) {
throw "$lock is a symlink/junction; remove it before running"
}
} Prevention
- Do not symlink or junction the config directory or its lock file.
- Exclude the config directory from cloud-sync tools that create reparse-point placeholders.
- Keep config under a plain local path (e.g. %USERPROFILE%\.codewhale).
- If the lock file looks suspicious, delete it and let the app recreate a real file.
When it happens
Trigger: Acquiring the config write lock on Windows when the lock file path resolves to a reparse point — e.g. the lock file is a symlink, the config directory is a junction, or a sync tool (Dropbox/OneDrive) replaced the file with a placeholder.
Common situations: Config directory symlinked to another location; cloud-sync placeholders standing in for real files; a malicious or accidental reparse-point planted at the lock path.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Codewhale-owned xAI OAuth path must not be a reparse point
- config path must not be a symlink
- external credential path contains reparse point
- external credential path must name a non-reparse regular…
- is a reparse point, not a workspace-owned file
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/62eef92b0b9552f4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/config_document.rs:253
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt as _;
use std::os::windows::fs::MetadataExt as _;
use std::os::windows::io::AsRawHandle as _;
use windows_sys::Win32::Storage::FileSystem::{
FILE_ATTRIBUTE_REPARSE_POINT, FILE_NAME_NORMALIZED, GetFinalPathNameByHandleW,
VOLUME_NAME_DOS,
};
let metadata = file.metadata().with_context(|| {
format!(
"failed to inspect config lock at {}",
crate::quote_os_path(expected_path)
)
})?;
if !metadata.file_type().is_file()
|| metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0
{
bail!(
"refusing non-regular or reparse-point config lock at {}",
crate::quote_os_path(expected_path)
);
}
let handle = file.as_raw_handle();
let flags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS;
// SAFETY: `handle` remains owned by `file`; a null output buffer asks for
// the required UTF-16 length.
let needed = unsafe { GetFinalPathNameByHandleW(handle, std::ptr::null_mut(), 0, flags) };
if needed == 0 {
return Err(std::io::Error::last_os_error()).with_context(|| {
format!(
"failed to resolve config lock at {}",
crate::quote_os_path(expected_path)
)
});
}View on GitHub (pinned to 73e0f67d83)