{"record":{"id":"b3be71906f138cc2","repo":"Hmbown/CodeWhale","slug":"config-lock-path-contains-invalid-unicode-and-c","errorCode":null,"errorMessage":"config lock path {} contains invalid Unicode and cannot be compared safely","messagePattern":"config lock path (.+?) contains invalid Unicode and cannot be compared safely","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/config_document.rs","lineNumber":301,"sourceCode":"            )\n        });\n    }\n    let actual = OsString::from_wide(&buffer[..written as usize]);\n    if normalize_windows_path_for_comparison(Path::new(&actual))?\n        != normalize_windows_path_for_comparison(expected_path)?\n    {\n        bail!(\n            \"config lock was redirected while opening {}\",\n            crate::quote_os_path(expected_path)\n        );\n    }\n    Ok(())\n}\n\n#[cfg(windows)]\nfn normalize_windows_path_for_comparison(path: &Path) -> Result<String> {\n    let text = path.to_str().ok_or_else(|| {\n        anyhow::anyhow!(\n            \"config lock path {} contains invalid Unicode and cannot be compared safely\",\n            crate::quote_os_path(path)\n        )\n    })?;\n    let without_device_prefix = text.strip_prefix(r\"\\\\?\\\").unwrap_or(text);\n    let normalized_prefix = without_device_prefix.strip_prefix(\"UNC\\\\\").map_or_else(\n        || without_device_prefix.to_string(),\n        |rest| format!(r\"\\\\{rest}\"),\n    );\n    Ok(normalized_prefix\n        .replace('/', \"\\\\\")\n        .trim_end_matches('\\\\')\n        .to_lowercase())\n}\n\nfn prepare_config_path(path: &Path) -> Result<PathBuf> {\n    let absolute = if path.is_absolute() {\n        path.to_path_buf()","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/config_document.rs#L283-L319","documentation":"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.","triggerScenarios":"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.","commonSituations":"Config directory placed under a path containing non-Unicode bytes, or paths assembled from legacy Windows APIs using the system ANSI codepage.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Windows-only guard before configuring a custom lock path\nif path.as_os_str().to_str().is_none() {\n    return Err(\"config lock path must be valid Unicode (UTF-8)\");\n}","typeGuard":"fn is_valid_unicode_path(p: &std::path::Path) -> bool {\n    p.to_str().is_some()\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["windows","path","unicode","file-lock"],"backgroundTag":"invalid-path-encoding","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}