{"record":{"id":"ffa939911833c64b","repo":"wezterm/wezterm","slug":"failed-to-query-locale","errorCode":null,"errorMessage":"failed to query locale","messagePattern":"failed to query locale","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"window/src/os/x11/keyboard.rs","lineNumber":825,"sourceCode":"        ensure!(\n            !new_keymap.get_raw_ptr().is_null(),\n            \"problem with new keymap\"\n        );\n\n        let new_state = xkb::x11::state_new_from_device(&new_keymap, connection, self.device_id);\n        ensure!(!new_state.get_raw_ptr().is_null(), \"problem with new state\");\n        let phys_code_map = build_physkeycode_map(&new_keymap);\n\n        self.state.replace(new_state);\n        self.keymap.replace(new_keymap);\n        self.phys_code_map.replace(phys_code_map);\n        Ok(())\n    }\n}\n\nfn query_lc_ctype() -> anyhow::Result<&'static OsStr> {\n    let ptr = unsafe { libc::setlocale(libc::LC_CTYPE, std::ptr::null()) };\n    ensure!(!ptr.is_null(), \"failed to query locale\");\n    let cstr = unsafe { CStr::from_ptr(ptr) };\n    Ok(OsStr::from_bytes(cstr.to_bytes()))\n}\n\nfn build_physkeycode_map(keymap: &xkb::Keymap) -> HashMap<xkb::Keycode, PhysKeyCode> {\n    let mut map = HashMap::new();\n\n    // See <https://abaines.me.uk/updates/linux-x11-keys> for info on\n    // these names and how they relate to the ANSI standard US keyboard\n    // See also </usr/share/X11/xkb/keycodes/evdev> on a Linux system\n    // to examine the mapping. FreeBSD and other unixes will use a different\n    // set of keycode values.\n    // We're using the symbolic names here to look up the keycodes that\n    // correspond to the various key locations.\n    for (name, phys) in &[\n        (\"ESC\", PhysKeyCode::Escape),\n        (\"FK01\", PhysKeyCode::F1),\n        (\"FK02\", PhysKeyCode::F2),","sourceCodeStart":807,"sourceCodeEnd":843,"githubUrl":"https://github.com/wezterm/wezterm/blob/3ff7522b9617ec920f7fbdb22b57e93d42d93ee9/window/src/os/x11/keyboard.rs#L807-L843","documentation":"query_lc_ctype calls libc setlocale(LC_CTYPE, NULL) to query the current LC_CTYPE setting, which returns a pointer to the locale string. A NULL return means the C library could not report a locale at all — typically because the process never had a valid LC_CTYPE (someone called setlocale with an unavailable name earlier) or the environment names a locale that isn't generated on the system. wezterm uses the result to feed locale-aware text handling on X11.","triggerScenarios":"LANG/LC_ALL/LC_CTYPE set to a locale that is not generated (e.g. 'en_US.UTF-8' on a minimal image where locales were never produced), leaving the C runtime with no usable LC_CTYPE; setlocale called earlier with an invalid name; chroot/sandbox without /usr/lib/locale data.","commonSituations":"Minimal Docker/Alpine images without locale-gen; SSH sessions forwarding LANG from a client whose locale the server lacks; Nix/Flatpak sandboxes with empty /usr/lib/locale; systems where only 'C' locale exists but env demands UTF-8.","solutions":["Set a safe locale explicitly before launching: `LC_ALL=C.UTF-8 wezterm` (C.UTF-8 needs no generated data on glibc)","Generate the requested locale on the host: Debian/Ubuntu — edit /etc/locale.gen, run locale-gen; Arch — locale-gen after /etc/locale.conf; Alpine — apk add musl-locales or use C.UTF-8","For SSH breakage, either install the client's locale on the server or configure sshd with AcceptEnv restricted / SendEnv disabled so bad LANG is not forwarded","Verify with `locale` — every printed variable should name a locale listed by `locale -a`"],"exampleFix":"# before: locale not generated, setlocale query fails\n$ LANG=en_US.UTF-8 wezterm\n\n# after: use the always-available C.UTF-8\n$ LC_ALL=C.UTF-8 wezterm","handlingStrategy":"validation","validationCode":"// ensure a usable locale before starting X11-dependent code\nlet name = std::env::var(\"LC_ALL\")\n    .or_else(|_| std::env::var(\"LC_CTYPE\"))\n    .or_else(|_| std::env::var(\"LANG\"))\n    .unwrap_or_else(|_| \"C.UTF-8\".into());\nif !name.ends_with(\"UTF-8\") && name != \"C\" {\n    std::env::set_var(\"LC_CTYPE\", \"C.UTF-8\");\n}","typeGuard":null,"tryCatchPattern":"let lc_ctype = query_lc_ctype().unwrap_or_else(|err| {\n    log::warn!(\"locale query failed ({err:#}); defaulting to C.UTF-8\");\n    OsStr::from_bytes(b\"C.UTF-8\")\n});","preventionTips":["Set LC_ALL=C.UTF-8 in service definitions and minimal containers instead of relying on inherited LANG","Run `locale -a` during image build and fail it if the configured locale is absent","Restrict AcceptEnv/SendEnv in sshd when clients and servers have disjoint locale sets"],"tags":["locale","x11","c-library","environment","wezterm"],"backgroundTag":"missing-locale","analyzedSha":"3ff7522b9617ec920f7fbdb22b57e93d42d93ee9","analyzedAt":"2026-08-20T04:47:31.434Z","contentChangedAt":"2026-08-20T04:47:31.434Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}