Hmbown/CodeWhale · error · anyhow::Error

config lock path {} contains invalid Unicode and cannot be c

Error message

config lock path {} contains invalid Unicode and cannot be compared safely

What it means

On Windows, after opening the config lock file the code verifies the lock was not redirected by normalizing both paths for comparison (stripping device and UNC prefixes, unifying separators). This error fires when the path cannot be converted to a string because it contains ill-formed Unicode (for example an unpaired surrogate), making a safe comparison impossible.

Source

Thrown at crates/config/src/config_document.rs:289

            )
        });
    }
    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 8880682c63)

Solutions

  1. Rename the offending directory or component to normal Unicode (or ASCII) using whatever tool created it
  2. Check the environment variable or flag that points Codewhale at its config directory for stray characters
  3. Workaround: point the config directory at a fresh ASCII path via the env var or flag and migrate the files
Defensive patterns

Strategy: validation

Validate before calling

// On Windows, verify the config lock path is valid Unicode before locking:
fn path_is_comparable_windows(p: &std::path::Path) -> bool {
    p.to_str().is_some()
}

Try / catch

On Err, abort startup rather than skipping the redirect check: the comparison exists to catch lock redirection, and an incomparable path cannot be verified. Suggest moving the config directory.

Prevention

When it happens

Trigger: The Windows-only normalization step runs on the config lock path; Path::to_str returns None when the path holds characters that are not valid Unicode, so the comparison aborts.

Common situations: Extremely rare: a junction or directory component created by a buggy script using raw ill-formed UTF-16; a config-directory environment variable holding such a path. Ordinary non-ASCII names (CJK, emoji) are valid Unicode and work fine.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/b3be71906f138cc2. Report an issue: GitHub.