rust-lang/rust · critical
cannot export more than U32_MAX files
Error message
cannot export more than U32_MAX files
What it means
Fires in the rmeta encoder (encoder.rs:330). After inserting a source file into `required_source_files`, the resulting index is converted to `u32` for serialization; `.expect("cannot export more than U32_MAX files")` panics if the index exceeds `u32::MAX`. It is a hard capacity guard: the on-disk metadata format addresses source files with a 32-bit index.
Solutions
- Identify and cap the macro/procedural generation that creates a unique `SourceFile` per iteration (e.g. `include_str!` in a loop, `concat!`/`file!`-expanding macros over a huge range).
- Reduce the number of distinct files fed to the crate (concatenate generated sources).
- If legitimate, this is a format limitation; file an issue to widen the index or stream source files.
- Audit `build.rs` / codegen steps that emit one file per entity.
Defensive patterns
Strategy: validation
Validate before calling
# Count distinct source files being fed to the crate; this guard only # fires near 2^32 files, so a hit means runaway generation. find . -name '*.rs' -type f | wc -l # sanity check the input is human-scale # If a macro generates files, cap its iteration range.
Prevention
- Cap macros/codegen that emit one `SourceFile` per loop iteration.
- Consolidate generated code into fewer files instead of one per entity.
- Audit `build.rs` codegen for unbounded file creation.
- Treat a hit here as a signal of runaway generation, not a normal build.
When it happens
Trigger: A compilation that registers more than 2^32 distinct `SourceFile`s in `required_source_files`. In practice unreachable for human-scale code; could conceivably arise from a pathological proc-macro / include! explosion that fabricates billions of synthetic source files.
Common situations: Essentially never in real projects; a guard rail. If hit, it indicates a runaway file-generation process (macro generating one source file per iteration of a huge range).
Related errors
- Already encoded SourceMap!
- missing source file
- argument names not encoded for a function
- no encoded attributes for a structure or variant
- no encoded ident for item
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/75f2e0bf13f977b5.
Report an issue: GitHub.
Appendix: source
Thrown at compiler/rustc_metadata/src/rmeta/encoder.rs:330
//
// All of this logic ensures that the final result of deserialization is a 'normal'
// Span that can be used without any additional trouble.
let metadata_index = {
// Introduce a new scope so that we drop the 'read()' temporary
match &*source_file.external_src.read() {
ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
src => panic!("Unexpected external source {src:?}"),
}
};
(SpanKind::Foreign, metadata_index)
} else {
// Record the fact that we need to encode the data for this `SourceFile`
let source_files =
s.required_source_files.as_mut().expect("Already encoded SourceMap!");
let (metadata_index, _) = source_files.insert_full(source_file_index);
let metadata_index: u32 =
metadata_index.try_into().expect("cannot export more than U32_MAX files");
(SpanKind::Local, metadata_index)
};
// Encode the start position relative to the file start, so we profit more from the
// variable-length integer encoding.
let lo = self.lo - source_file.start_pos;
// Encode length which is usually less than span.hi and profits more
// from the variable-length integer encoding that we use.
let len = self.hi - self.lo;
let tag = SpanTag::new(kind, ctxt, len.0 as usize);
tag.encode(s);
if tag.context().is_none() {
ctxt.encode(s);
}
lo.encode(s);View on GitHub (pinned to 7088e4b63a)