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

  1. 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).
  2. Re-export the variable as plain ASCII: `export CG_CLIF_JIT_ARGS="--arg1 --arg2"` from a UTF-8 shell.
  3. Unset it if JIT args are not needed: `unset CG_CLIF_JIT_ARGS`.
  4. 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

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


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/19a39fa61b69bcfd.json. Report an issue: GitHub.