rust-lang/rust · critical
failed to lookup `SourceFile` in new context
Error message
failed to lookup `SourceFile` in new context
What it means
During incremental-cache deserialization, `CacheDecoder::file_index_to_file` (on_disk_cache.rs:439) calls `source_map().source_file_by_stable_id(...).expect("failed to lookup SourceFile in new context")`. The decoder has already confirmed the source file's `StableCrateId` resolves to a crate and has imported that crate's source files; if `source_file_by_stable_id` still returns `None`, the stable source-file ID persisted in the cache no longer matches any file in the current session.
Source
Thrown at compiler/rustc_middle/src/query/on_disk_cache.rs:439
let source_file_cnum = tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id);
// If this `SourceFile` is from a foreign crate, then make sure
// that we've imported all of the source files from that crate.
// This has usually already been done during macro invocation.
// However, when encoding query results like `TypeckResults`,
// we might encode an `AdtDef` for a foreign type (because it
// was referenced in the body of the function). There is no guarantee
// that we will load the source files from that crate during macro
// expansion, so we use `import_source_files` to ensure that the foreign
// source files are actually imported before we call `source_file_by_stable_id`.
if source_file_cnum != LOCAL_CRATE {
self.tcx.import_source_files(source_file_cnum);
}
tcx.sess
.source_map()
.source_file_by_stable_id(source_file_id.stable_source_file_id)
.expect("failed to lookup `SourceFile` in new context")
}))
}
// copy&paste impl from rustc_metadata
#[inline]
fn decode_symbol_or_byte_symbol<S>(
&mut self,
new_from_index: impl Fn(u32) -> S,
read_and_intern_str_or_byte_str_this: impl Fn(&mut Self) -> S,
read_and_intern_str_or_byte_str_opaque: impl Fn(&mut MemDecoder<'a>) -> S,
) -> S {
let tag = self.read_u8();
match tag {
SYMBOL_STR => read_and_intern_str_or_byte_str_this(self),
SYMBOL_OFFSET => {
// read str offset
let pos = self.read_usize();View on GitHub (pinned to 22057b88b0)
Solutions
- Remove the stale incremental cache: `rm -rf target/<triple>/incremental target/debug/incremental` and rebuild.
- Run a full `cargo clean && cargo build` if the above is insufficient.
- Disable incremental compilation for this configuration: `CARGO_INCREMENTAL=0`.
- Audit CI caches that reuse `target/`; ensure they are keyed on the exact source commit and toolchain.
- Avoid mixing `--remap-path-prefix` values (or cargo profile differences) across sessions that share an incremental dir.
Example fix
# before $ vim src/lib.rs # edit a file referenced by another crate's cache $ cargo build # panic: failed to lookup `SourceFile` in new context # after $ cargo clean -p <affected-crate> $ cargo build # rebuilds incremental DB for that crate
Defensive patterns
Strategy: fallback
Validate before calling
// Detect a toolchain/crate-structure change that would invalidate SourceFile indices,
// then proactively drop the incremental cache before building.
use std::fs;
use std::path::{Path, PathBuf};
fn cache_freshness_ok(target: &Path, fingerprint_path: &Path) -> bool {
// Write the rustc commit hash + crate count into fingerprint_path on every clean build.
let current = format!("{}\n{}\n",
std::process::Command::new("rustc").arg("-vV").output()
.ok().and_then(|o| String::from_utf8(o.stdout).ok()).unwrap_or_default(),
fs::read_dir(target).map(|d| d.count()).unwrap_or(0));
match fs::read_to_string(fingerprint_path) {
Ok(prev) => prev == current,
Err(_) => { let _ = fs::write(fingerprint_path, ¤t); true }
}
}
fn build_safe(dir: &Path) -> std::io::Result<std::process::ExitStatus> {
let target = dir.join("target");
if !cache_freshness_ok(&target, &target.join(".inc_fingerprint")) {
let inc = target.join("debug").join("incremental");
let _ = fs::remove_dir_all(&inc);
}
std::process::Command::new("cargo").arg("build").current_dir(dir).status()
} Prevention
- Clear incremental cache after upgrading the toolchain (rustup / nightly bump).
- Do not reuse `target/` after large refactors that delete or rename many files.
- In CI, always build from a clean state to avoid stale SourceFile mappings.
- If you cache `target/` across CI runs, scope the cache key to the rustc version.
When it happens
Trigger: Fires when the incremental cache encodes a reference to a `SourceFile` (e.g. inside encoded typeck/mir results) whose `StableSourceFileId` was computed under one set of inputs but is being looked up under another—typically after the source file's content, path, or hashing inputs changed between the session that wrote the cache and the one reading it.
Common situations: Seen after editing a file that another crate's incremental cache references (especially with proc-macro or include-str style indirection), after `cargo` reorders crate paths, after a `rustfmt`/editor rewrite between compile sessions, after switching remapped path prefixes (`--remap-path-prefix`), or when a CI cache layer persists `target/incremental` across a source commit it shouldn't have.
Related errors
- Incremental cache file size overflowed u64.
- Bad hash {:?} (map {:?})
- Failed to convert DefPathHash {def_path_hash:?}
- counting sort fills every slot of a kind's range
- Invalid tag for ClearCrossCrate: {tag:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/bbce0ca87849a6cb.json.
Report an issue: GitHub.