A practical Rust reference
Symptom → mechanism → evidence
Rust Failure Atlas
A field guide for Rust failures that are difficult to name and easy to misdiagnose. Start from what you can observe, isolate the mechanism, reproduce it, and verify the repair.
The front of this page collects failures below the application layer: an FFI symbol that disappears under LTO, a linker killed for memory, a sys crate that finds the wrong native library, two copies of one native library in one binary, a C object built for the host instead of the target, memory freed by the wrong allocator, and a doctest that sees a different cfg. The full collection, including compiler diagnostics with a stable error code, stays searchable below and on the family pages.
704
symptom-first records
689
records with a downloadable failing and repaired fixture; 15 link to articles without an executable fixture yet
99
mechanism trails connecting related failures
Below the application layer
Linkers, native libraries, targets, and runtimes
These 27 cases depend on more than the source file: the final link, a symbol table, a C toolchain, the target triple, the allocator on the other side of an FFI call, a Cargo profile, or the test harness. For 16 of them the fixture goes past a single compiler run: nm and readelf, a link map, a linker under a memory cap, a C host built with AddressSanitizer, paired Cargo profiles, or a subprocess deadline.
Linking and symbol export
What the final artifact actually exports, which symbols survive LTO, and what the linker needs to finish.
- RFA-039 · Native symbol-matrix evidenceWhy a Rust FFI Symbol Disappeared After Enabling LTOBuilds a Rust staticlib with and without thin LTO, reads both symbol tables with nm, and links a C host against the result.
- RFA-125 · Linker evidenceWhy an extern Function Compiles but Fails With an Undefined SymbolCompiles and links one file. The failing file must stop at the final link with the recorded error and the repaired file must link and run.
- RFA-040 · Link resource-matrix evidenceWhy the Linker Is Killed Only During a Rust Release BuildLinks the same Rust objects with ld.lld under a normal and a capped memory limit, then with ld.bfd under the same cap.
- RFA-707 · Compiler evidenceA Rust Runtime Symbol Is More Than an Exported NameExporting a name such as memset defines a symbol the standard library itself calls with a fixed ABI.
Native libraries and cross-compilation
Which native library a build script finds, who owns it in the graph, and which machine its objects are built for.
- RFA-041 · Native target-matrix evidenceA Rust Native Dependency Built for the Host Instead of the TargetRuns the build script with HOST and TARGET set for a cross build and reads the machine type of the produced object with readelf.
- RFA-042 · Native discovery evidenceWhy a Rust sys Crate Found the Wrong Native LibraryBuilds two installations of one native library and runs the build script with header and library discovery pointing at different installations.
- RFA-043 · Native ownership evidenceTwo Rust Dependencies Linked Incompatible Copies of One Native LibraryBuilds two versions of a native library, links a Rust consumer, and reads the final link map to see which versions were linked.
- RFA-104 · Cargo workspace evidenceHow Cargo's links Conflict Reveals Two Owners of One Native LibraryCargo's links key is the one place where the build graph records ownership of a native library.
- RFA-694 · Cargo workspace evidenceCargo DEP_* Metadata Stops at the Immediate DependentDEP_* metadata from a links package reaches only immediate dependents, not the whole graph.
FFI ownership, ABI, and unwinding
Which side owns an allocation, what a value means on the other side of the boundary, and what a panic may cross.
- RFA-046 · Allocator sanitizer evidenceMemory Allocated on One Side of Rust FFI Was Freed on the OtherLinks a Rust staticlib into a C host built with clang AddressSanitizer, which reports a free through the wrong allocator.
- RFA-044 · Cargo workspace evidenceA Rust Enum Crossed C Safely Until a New Variant Was AddedAn enum crossing a C boundary needs a fixed representation and a plan for values the Rust side does not know.
- RFA-045 · Runtime evidenceWhat Happens When a Rust Panic Reaches an extern BoundaryWhether a panic may unwind through foreign frames depends on the ABI string and the panic strategy.
- RFA-145 · Runtime evidenceWhy a Panic in Drop During Unwinding Aborts the ProcessA second panic from a destructor during unwinding turns into a process abort before any catch boundary runs.
- RFA-695 · Cargo workspace evidenceA no_std Rust Binary Needs Exactly One Panic HandlerWithout std there is no panic runtime, so a no_std binary must define exactly one panic handler.
Build scripts, profiles, and test harnesses
When Cargo reruns a build script, what a profile changes, and how doctests and packaging see a different crate.
- RFA-050 · Cargo test-surface evidenceWhy a Rust Doctest Sees Different cfg Values From a Normal TestRuns the library unit tests and the doctests of the same package separately.
- RFA-037 · Cargo profile-pair evidenceWhy Integer Overflow Behaves Differently in Rust Debug and Release BuildsRuns the same package under the dev and release profiles and compares the results.
- RFA-032 · Cargo package-boundary evidenceA Cargo Workspace Builds Locally but the Packaged Crate Misses FilesChecks the package inside the workspace, then runs cargo package to build it the way a registry consumer would.
- RFA-697 · Cargo rebuild evidenceA build.rs Environment Input Needs rerun-if-env-changedRuns the package twice with a different environment value and compares the generated output.
- RFA-705 · Cargo runtime-boundary evidencecargo::rustc-env Is Not a Portable Runtime Environment VariableRuns the binary through cargo run and then directly, and compares what it reads from its environment.
- RFA-693 · Cargo workspace evidenceCargo Gives TARGET to build.rs at Run Time, Not Compile TimeTARGET is set when Cargo runs the compiled build script, not while rustc compiles build.rs.
- RFA-102 · Cargo workspace evidenceWhen Cargo Feature Unification Enables Mutually Exclusive FeaturesCargo merges feature requests from every path into one package instance, so exclusive features collide.
Runtimes, scheduling, and layout
Timers, blocking work, wakeups, shared test processes, and layout decisions that only show up when the program runs.
- RFA-029 · Cargo deadline-isolated evidenceA Tokio Test With Paused Time Never AdvancesBuilds the binary and runs it as a subprocess with a deadline.
- RFA-030 · Cargo deadline-isolated evidencespawn_blocking Work Keeps a Tokio Runtime Alive During ShutdownBuilds the binary and runs it as a subprocess with a deadline.
- RFA-033 · Cargo suite-isolation evidenceWhy a Rust Test Hangs Only in the Full Test SuiteRuns each test on its own, then the whole suite under a timeout.
- RFA-036 · Cargo workspace evidenceWhy a Rust Stream Stops Forever After Returning PendingA hand-written Stream must register its waker before it returns Pending, or no task is ever woken again.
- RFA-038 · Invariant matrix evidenceA Rust Release Crash Disappears When Logging Is AddedBuilds the program at opt-level 0 and 3 and runs each build with and without logging.
- RFA-301 · Runtime evidenceUnsafeCell Can Disable an Outer Option Niche OptimizationUnsafeCell keeps its inner layout but hides the null niche that Option would otherwise reuse.
01
Begin with the symptom
Use the exact message, target, timing, profile, and smallest environmental difference you can observe.
02
Run a discriminating check
Prefer one test that separates two possible causes over a long list of generic fixes.
03
Keep the fixture with the repair
Each case page ships a failing and a repaired fixture. The fixture shows that the failure reproduces and that the repair passes. The explanation is written by hand, and you can check it against the fixture.
Find the failure you actually have
Search error fragments and observed behavior. The first check is deliberately narrow: it should remove a branch from the diagnosis, not merely produce more logs.
Browse the failure families below, or search to load the detailed records.
Inclusion standard
A plausible explanation is not yet a case file
I include a failure when I can state the symptom without pretending it has only one cause, show a minimal or controlled reproduction, identify at least one misleading shortcut, and connect the repair to evidence that would fail again if the mechanism returned.
A fixture run shows two things: the failing project fails with the recorded output, and the repaired project passes. It does not check the written explanation, which is my reading of the mechanism with primary sources cited on each case page. 15 records link to long-form articles instead of case pages. They do not have an executable fixture yet, and search results say so.
- Exact toolchain, target, profile, and dependency context
- Small reproduction or controlled interleaving
- Likely cause separated from confirmed cause
- A repair with a regression check
- Primary documentation or upstream implementation source
- A review date when version-sensitive behavior matters
Reference layer
Compiler diagnostics and library contracts
The other 677 records are the reference layer. Most of them start from a compiler diagnostic or a documented standard library contract, where the cause is closer to the code you wrote: borrow and trait errors, macro and type diagnostics, collection and I/O behavior, numeric edge cases, and edition changes. 322 of them are keyed to a compiler error code. All of them stay in search and on their family pages.
A case belongs in the atlas when copying the final fix without understanding the mechanism is likely to make the failure return in another target, task, dependency, or release. For language concepts without a failure symptom, use the Rust Under the Hood series. For a compiler error code on its own, the official Rust error-code index is usually the faster reference.
Add evidence, not noise
Have a Rust failure that disappears when simplified?
Send the smallest evidence you still trust: the symptom, versions, target, profile, and what makes it appear or disappear. A useful report can become an Atlas case without exposing private source code.
Share a reproducible symptom