rust-lang/rust · error

valid UTF-8

Error message

valid UTF-8

What it means

Thrown by `CStr::from_ptr(pass_name).to_str().expect("valid UTF-8")` in `selfprofile_before_pass_callback` (profiling.rs:53). This callback runs only when self-profiling (`-Z self-profile` / `-Z self-profile-events`) is enabled; LLVM passes the C-string name of an optimization pass back to rustc, and this expect fires if that name is not valid UTF-8. In practice LLVM pass names are ASCII, so this panic indicates a memory-safety/FFI contract violation or an LLVM build that emitted garbage pass names.

Source

Thrown at compiler/rustc_codegen_llvm/src/back/profiling.rs:53

    fn before_pass_callback(&'a mut self, pass_name: &str, ir_name: &str) {
        let event_id = llvm_args_to_string_id(&self.profiler, pass_name, ir_name);

        self.stack.push(TimingGuard::start(&self.profiler, self.llvm_pass_event_kind, event_id));
    }
    fn after_pass_callback(&mut self) {
        self.stack.pop();
    }
}

pub(crate) unsafe extern "C" fn selfprofile_before_pass_callback(
    llvm_self_profiler: *mut c_void,
    pass_name: *const c_char,
    ir_name: *const c_char,
) {
    unsafe {
        let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
        let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
        let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
        llvm_self_profiler.before_pass_callback(pass_name, ir_name);
    }
}

pub(crate) unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) {
    let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) };
    llvm_self_profiler.after_pass_callback();
}

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Use the official rustup toolchain instead of a custom-built rustc+LLVM to rule out an ABI/name mismatch.
  2. If using a custom LLVM, audit any out-of-tree or patched passes for non-ASCII/uninitialized pass-name strings passed to the callback registration.
  3. Temporarily disable self-profiling (`-Z self-profile=` unset) to confirm the crash is profiling-callback-specific.
  4. Rebuild the rustc/LLVM toolchain cleanly (clobber) to eliminate stale-object ABI drift.
  5. Report to the rustc team with the LLVM revision and pass name bytes if reproducible on stock toolchain.

Example fix

# before: self-profile triggers FFI UTF-8 panic on custom LLVM
RUSTFLAGS='-Z self-profile=/tmp/profile' cargo build

# after: drop self-profile and/or switch to stock toolchain
# 1) stop profiling
cargo build
# 2) or use official toolchain
rustup default stable
Defensive patterns

Strategy: try-catch

Try / catch

let res = std::panic::catch_unwind(|| {
    // path that enables -Zself-profile (LLVM pass-name callback)
    run_codegen_with_self_profile()
});
if res.is_err() {
    // LLVM emitted a non-UTF-8 pass name; disable self-profile and retry.
    run_codegen_without_self_profile();
}

Prevention

When it happens

Trigger: Triggered when the compiler is built/run with self-profiling enabled AND LLVM invokes the registered `selfprofile_before_pass_callback` with a `pass_name` pointer whose bytes are not valid UTF-8 (e.g. uninitialized pointer, mis-registered pass name from a custom/out-of-tree LLVM pass, or a corrupted LLVM C-string).

Common situations: Using a custom or patched LLVM with a pass that registers a non-UTF-8/garbage name; an LLVM/rustc ABI mismatch after a botched toolchain build; memory corruption from a faulty LLVM plugin; rare when using the official rustup toolchain. Almost never seen with stock LLVM.

Related errors


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