libnyanpasu/clash-nyanpasu · info
`en-US` is a valid BCP47 language tag
Error message
`en-US` is a valid BCP47 language tag
What it means
locale_or_fallback converts a system locale string into a LanguageTag, defensively parsing and canonicalizing because sys-locale output isn't guaranteed valid. If parsing fails (or input is None), it falls back to a hardcoded "en-US" whose parse is asserted with .expect — the panic fires only if that constant stops parsing, i.e. a broken regex/parser or edited constant.
Source
Thrown at backend/nyanpasu-helper/src/locale.rs:29
}
/// Parse and canonicalize a raw locale string, falling back to `en-US` when it
/// is absent or not a valid BCP47 language tag.
///
// FIXME(sys-locale): `sys_locale::get_locale` documents that it returns a
// BCP47 tag, but its Unix backend does not enforce this. It merely transforms
// the `LANG` / `LC_*` environment variables (stripping `.<codeset>` / `@<mod>`
// and turning `_` into `-`) without validating the grammar or filtering the
// POSIX `C` / `POSIX` locales. On minimal Linux/CI environments where the
// locale is `C` / `C.UTF-8`, it returns `Some("C")` — a single-letter primary
// subtag that is *not* a valid BCP47 language tag — instead of `None`. We must
// therefore parse defensively here rather than trusting the documented
// contract. Revisit if a future `sys-locale` release returns `None` for the
// POSIX locale.
fn locale_or_fallback(raw: Option<&str>) -> LanguageTag {
raw.and_then(|raw| LanguageTag::parse(raw).ok()?.canonicalize().ok())
.unwrap_or_else(|| {
LanguageTag::parse("en-US").expect("`en-US` is a valid BCP47 language tag")
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_system_locale() {
// Must never panic regardless of the host locale.
let locale = get_system_locale();
eprintln!("System locale: {}", locale);
}
#[test]
fn invalid_or_absent_locale_falls_back_to_en_us() {
let fallback = LanguageTag::parse("en-US").unwrap();
// The `C` locale (common in CI) has a single-letter primary subtag,View on GitHub (pinned to f7dbce2997)
Solutions
- Do not modify the "en-US" fallback constant to a non-BCP47 value.
- If you need a different default, verify it parses with LanguageTag::parse before committing.
- Check for vendored/broken versions of the language-tags crate if this panics.
- Add a unit test asserting the fallback parses, so a bad edit fails at test time instead of runtime.
Example fix
// before: invalid fallback edit
LanguageTag::parse("en_US").expect("`en-US` is a valid BCP47 language tag")
// after: keep a valid BCP47 tag
LanguageTag::parse("en-US").expect("`en-US` is a valid BCP47 language tag") Defensive patterns
Strategy: validation
Validate before calling
// Verify any custom fallback parses at startup
fn valid_fallback(tag: &str) -> bool { LanguageTag::parse(tag).is_ok() }
assert!(valid_fallback("en-US")); Try / catch
catch_unwind around locale resolution; on panic, fall back to a raw string locale.
Prevention
- Never edit the "en-US" fallback to a non-BCP47 value.
- Add a unit test asserting the fallback parses.
- Pin/verify the language-tags crate version.
- Validate any new default locale with LanguageTag::parse first.
When it happens
Trigger: Triggered only when LanguageTag::parse("en-US") fails — practically impossible unless the language-tags crate is broken, the constant was edited to an invalid tag, or parsing is misconfigured (e.g. custom parser rejecting valid tags).
Common situations: Not hit in real deployments. Developers encounter it conceptually when changing the fallback constant or vendoring an incompatible version of the parsing crate.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Local socket too many crashes
- invalid url
- should never drop oneshot tx
- semaphore should never closed
- version overflow
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/ac38effd12606548.
Report an issue: GitHub.