Hmbown/CodeWhale · error
config lock path contains invalid Unicode and cannot be…
Error message
config lock path {} contains invalid Unicode and cannot be compared safely What it means
On Windows, `normalize_windows_path_for_comparison` converts lock-file paths to a canonical string form (stripping `\\?\` device and `UNC\` prefixes) so lock handles can be compared. If the path cannot be represented as valid Unicode (`Path::to_str()` returns None), comparison would be unsafe, so it fails with this error. Only reachable on Windows.
Solutions
- Rename the config directory (or set the config path) to a location using only valid Unicode characters.
- Check the config-path environment/CLI override for accidentally garbled bytes.
- Ensure the path is valid UTF-8: use `PathBuf` from UTF-8 strings, not raw byte sources.
Defensive patterns
Strategy: validation
Validate before calling
// Windows-only guard before configuring a custom lock path
if path.as_os_str().to_str().is_none() {
return Err("config lock path must be valid Unicode (UTF-8)");
} Type guard
fn is_valid_unicode_path(p: &std::path::Path) -> bool {
p.to_str().is_some()
} Prevention
- Place the config directory under a plain ASCII/UTF-8 path
- Avoid building paths from raw OS byte strings on Windows
- Check any config-path override env var for garbled characters
When it happens
Trigger: Calling code that validates a Windows lock handle (`validate_windows_lock_handle`) with a path built from invalid UTF-8 bytes (e.g. from `OsString`/raw filesystem APIs) in the config lock path.
Common situations: Config directory placed under a path containing non-Unicode bytes, or paths assembled from legacy Windows APIs using the system ANSI codepage.
Related errors
- xAI OAuth path contains invalid Unicode and cannot be…
- Codewhale-owned xAI OAuth path has the wrong filesystem type
- credential path contains invalid Unicode and cannot be…
- agent profile path is not a directory
- Another pet owner is running
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b3be71906f138cc2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/config_document.rs:301
)
});
}
let actual = OsString::from_wide(&buffer[..written as usize]);
if normalize_windows_path_for_comparison(Path::new(&actual))?
!= normalize_windows_path_for_comparison(expected_path)?
{
bail!(
"config lock was redirected while opening {}",
crate::quote_os_path(expected_path)
);
}
Ok(())
}
#[cfg(windows)]
fn normalize_windows_path_for_comparison(path: &Path) -> Result<String> {
let text = path.to_str().ok_or_else(|| {
anyhow::anyhow!(
"config lock path {} contains invalid Unicode and cannot be compared safely",
crate::quote_os_path(path)
)
})?;
let without_device_prefix = text.strip_prefix(r"\\?\").unwrap_or(text);
let normalized_prefix = without_device_prefix.strip_prefix("UNC\\").map_or_else(
|| without_device_prefix.to_string(),
|rest| format!(r"\\{rest}"),
);
Ok(normalized_prefix
.replace('/', "\\")
.trim_end_matches('\\')
.to_lowercase())
}
fn prepare_config_path(path: &Path) -> Result<PathBuf> {
let absolute = if path.is_absolute() {
path.to_path_buf()View on GitHub (pinned to 73e0f67d83)