rust-lang/rust · error
CG_CLIF_JIT_ARGS not unicode: {:?}
Error message
CG_CLIF_JIT_ARGS not unicode: {:?} What it means
Panics inside BackendConfig::from_opts while reading the CG_CLIF_JIT_ARGS environment variable when its bytes are not valid UTF-8. The variable carries CLI arguments passed to the program under JIT mode; non-UTF-8 cannot be split into String args, so the backend aborts before codegen.
Source
Thrown at compiler/rustc_codegen_cranelift/src/config.rs:24
/// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`.
pub jit_mode: bool,
/// When JIT mode is enable pass these arguments to the program.
///
/// Defaults to the value of `CG_CLIF_JIT_ARGS`.
pub jit_args: Vec<String>,
}
impl BackendConfig {
/// Parse the configuration passed in using `-Cllvm-args`.
pub fn from_opts(opts: &[String]) -> Result<Self, String> {
let mut config = BackendConfig {
jit_mode: false,
jit_args: match std::env::var("CG_CLIF_JIT_ARGS") {
Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
Err(std::env::VarError::NotPresent) => vec![],
Err(std::env::VarError::NotUnicode(s)) => {
panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s);
}
},
};
for opt in opts {
if opt.starts_with("-import-instr-limit") {
// Silently ignore -import-instr-limit. It is set by rust's build system even when
// testing cg_clif.
continue;
}
match &**opt {
"jit-mode" => config.jit_mode = true,
_ => return Err(format!("Unknown option `{}`", opt)),
}
}
Ok(config)
}View on GitHub (pinned to 22057b88b0)
Solutions
- Inspect the raw bytes: `printf '%s' "$CG_CLIF_JIT_ARGS" | hexdump -C` and look for non-UTF-8 (e.g. 0x96, 0xa0, BOM EF BB BF).
- Re-export the variable as plain ASCII: `export CG_CLIF_JIT_ARGS="--arg1 --arg2"` from a UTF-8 shell.
- Unset it if JIT args are not needed: `unset CG_CLIF_JIT_ARGS`.
- Fix the upstream script that produces the value (strip BOM, normalize encoding to UTF-8).
Example fix
// before
Err(std::env::VarError::NotUnicode(s)) => {
panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s);
}
// after
Err(std::env::VarError::NotUnicode(s)) => {
let lossy = s.to_string_lossy().into_owned();
panic!("CG_CLIF_JIT_ARGS not unicode (raw={:?}, lossy={:?}). Set it to UTF-8 ASCII args.", s, lossy);
} Defensive patterns
Strategy: validation
Validate before calling
fn check_jit_args() -> Result<(), String> {
match std::env::var_os("CG_CLIF_JIT_ARGS") {
None => Ok(()),
Some(v) => match v.to_str() {
Some(_) => Ok(()),
None => Err("CG_CLIF_JIT_ARGS contains non-UTF8 bytes; remove or re-export as UTF-8".to_string()),
},
}
}
// call before running the cranelift JIT entrypoint Type guard
fn jit_args_is_unicode() -> bool {
std::env::var_os("CG_CLIF_JIT_ARGS")
.map(|v| v.to_str().is_some())
.unwrap_or(true)
} Prevention
- Always set CG_CLIF_JIT_ARGS from a Rust String/&str (UTF-8) rather than OsString built from raw bytes.
- In CI, export the env var from a UTF-8 source; avoid piping non-UTF8 shell variables into it.
- Do not point CG_CLIF_JIT_ARGS at paths with non-UTF8 components; use UTF-8 path aliases instead.
- If unsure, unset the variable rather than guess; the JIT defaults to no extra args.
When it happens
Trigger: Reached when std::env::var returns VarError::NotUnicode during JIT configuration parsing (config.rs:23-25). Any byte sequence that fails UTF-8 validation trips it, regardless of jit-mode actually being requested.
Common situations: A shell or wrapper script exports CG_CLIF_JIT_ARGS from a binary/locales-aware source (e.g. xargs over a file with CRLF or Latin-1 bytes); the variable was set by a tool that injected a BOM or NUL; CI sets it via a YAML that mangled quotes into smart-quotes; copied from a Windows cmd session with a non-UTF-8 codepage.
Related errors
- failed to create {dst:?}: {e}
- failed to copy {src:?}->{dst:?}: {e}
- Failed to spawn cargo: {}
- Failed to spawn rustc: {}
- Failed to spawn rustdoc: {}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/19a39fa61b69bcfd.json.
Report an issue: GitHub.