---
name: disk-full-reds-as-lnk1318-pdb-error
description: "A nearly-full C: reds builds as LNK1318 'Unexpected PDB error; LIMIT (12)' — reads as a corrupt PDB or toolchain fault; the tell is that traceable-reqs alone survives."
metadata: 
  node_type: memory
  type: reference
  originSessionId: 97bd4780-202d-4522-9abc-8ac75f327f07
  modified: 2026-08-05T02:08:21.741Z
---

**Measured 2026-08-04 (todlando, HFENDULEAM).** C: hit **0.44 GB free of 1862 GB**. A lane redded
6 of 7 legs with:

```
LINK : fatal error LNK1318: Unexpected PDB error; LIMIT (12)
```

on `spt.pdb`. It reads as a corrupt PDB or a broken toolchain. It is neither — it is the linker
unable to grow a 333 MB PDB on a full disk. **Nothing in the failure text says "disk".**

**The positive tell:** `traceable-reqs` exited 0 while build, units, clippy and drift all exited
101. traceable-reqs is the only leg that **never links**. A leg table where treqs alone survives is
the disk's signature, not the lane's. Same family of suspicion for `os error 112` and any
mysterious mid-build I/O red.

**⚠ It is a positive tell, NOT a clearing test (hertz, same day).** Signature absent says *nothing*:
- a full disk can red **before any link step** (rustc writing rlibs / incremental), so no LNK1318
  appears at all and treqs is not uniquely the survivor;
- treqs can red for its own reasons (a missing tag), erasing the signature while the disk is still
  the cause.

So "my table doesn't look like that one" is not a clean bill of health. **The falsifier for "this
red was the disk" is FREE SPACE AT THE TIME OF THE RUN** — not the shape of the leg table.

**Standing gap on this box:** no rig or gate log records free space at run start, so "was the disk
full" is unanswerable after the fact for every red already in hand. Any red produced while free
space was under ~1 GB is **uninterpretable and must be re-run, not re-read** — same rule as
[[intermittent-green-is-zero-information]]: a red under an unmeasured confound is not evidence about
the lane in either direction.

**Context for the size:** ~198 GB of cargo build caches across `.worktrees` pools produced this.
Reaping finished lanes' target subtrees recovered it (0.44 -> ~60 GB). Teardown discipline is
[[quoted-measurement-decays-when-you-mutate-the-subject]]-adjacent: classify OUTBOUND (junction vs
real tree) before deleting, sweep INBOUND reparse points, check `CARGO_TARGET_DIR` (the env-var face
leaves no directory entry a dir sweep can see), and report free-space delta rather than
sum-of-file-lengths — the two disagreed by 8% on one reap.

Kin: [[measure-the-box-before-the-instrument]], [[tool-claim-must-name-its-environment]],
[[rig-inherits-the-defect-it-studies]].

---

**⚠ SECOND FACE, 2026-08-22 (todlando + doyle, same box).** The entry above records a disk that was
ALREADY full. This one was a disk **being drained by the build that failed**, and it is the commoner
shape: free went 135.44 GB -> under 5 GB while two lane pools built COLD (74.4 GB + 47.3 GB = ~122 GB
of allocation), and `LNK1318: Unexpected PDB error; OK (0)` landed on the link of `spt` — the LAST
and LARGEST artifact of the 74 GB pool that was itself eating the volume. A `cargo clean -p spt-net`
then "fixed" it, which is a FALSE CONFIRMATION of a corrupt-artifact theory: by the retry the pool
was already built, so the incremental space needed was a fraction. **The clean freed 664 MB and was
never the cause of the recovery.**

Note the variant text: `OK (0)` here, `LIMIT (12)` above. Same defect, different parenthetical — do
not key recognition on the code.

**Cost of not reading this file:** two agents re-derived the mechanism from scratch, ranked
mspdbsrv-contention FIRST on a signature match, and designed a contention experiment that would have
been confounded (run 1 had low disk AND contention; any rerun today has 130+ GB free, so a
non-reproduction would have said nothing). doyle retracted it himself before firing. The rule he
adopted — **free space goes in the FIRST LINE of any build-failure report, not in the controls** —
is this file's own "standing gap" bullet, re-earned at full cost.

**Tell that would have caught it in one command:** `df -h` / `(Get-PSDrive C).Free`. Neither of us
ran it, not because it was hard but because nobody thought the resource was interesting.

---

**⚠ THIRD FACE, 2026-09-09 (hertz, HFENDULEAM) — the disk red arrived as a PRODUCT ASSERTION, with
no build or link step involved at all.** C: reached **0.018 GiB free of 1862.02 GiB (0.00%)**. The
failing leg was not a build: it was a passing-elsewhere integration test, and what it printed was a
panic in OUR code at `crates\spt-daemon\tests\sync.rs:198`:

```
pull: Custom { kind: Other, error: "sync refused: bundle failed: git -C ...\tracked-b\.seed.git
bundle create ...\serve-pull-6.bundle ^d12a713... a-doyle failed (exit Some(1)):
fatal: sha1 file '<stdout>' write error. Out of diskspace\nerror: pack-objects died" }
```

`sync refused` is a real product refusal string. The disk cause is the FOURTH clause of a nested
error, past a git exit code, and everything before it reads as a sync-layer regression at the sha
under test. I had the head sha and the old sha side by side in a discriminator; the head arm's
single FAIL would have been reported as a head regression by anyone who stopped reading at
`sync refused: bundle failed`. **Read the innermost cause of a wrapped error before attributing the
outer one to the code under test.**

So this file's family now spans three distinct costumes for one cause — LNK1318 at link,
rustc/incremental I/O before any link, and a product-level refusal assertion inside a test — which
is exactly why the file's own rule holds: the falsifier is **free space at the time of the run**,
never the shape of the failure. The two earlier faces both looked like the toolchain; this one
looked like the product, which is worse, because a product costume routes to a code owner and gets
a bisect rather than a `df`.

**Scale note, for anyone sizing a pool budget:** ~195 GiB of headroom went to nothing exotic,
accrued across a ~45-minute build phase. **No reading here bounds a RATE** — the free-space
observations either side are endpoints of an accrual, and a rate derived from them is fiction that
retargets the hunt: deployah's '>150 MB/s' (from a figure doyle asserted) sent him after runaway
logs, VSS and torrent preallocation, while the live box-wide write rate measured ~1.5 MB/s. What
consumed it: two `cargo nextest run -E <5-test filter>` lanes at **82.88 and 64.44 GiB**
(a filter does not narrow the BUILD; both built 221 test binaries under the `test` profile), plus
40.93 GiB of `C:\actions-runner\_work` and 9.8 GiB of `%TEMP%`. Reclaim was 81.87 and 63.32 GiB
actual against those Length-sums — 1.2% and 1.8% over, the hardlink gap again, third and fourth
instances of it.

**It wedged the daemon. Whether the wedge lifted with the space is NOT established — and my
claiming it was is the instructive part.** doyle read `spt daemon status` mid-
incident as peer pump last tick 185 s ago, 24 brain subscribers stall-evicted, `SERVE_UNCONFIRMED`
on serve list, and was weighing an operator restart (which risks the #287 shell stranding). After
the reclaim I took ONE sample — peer pump live at 54 s, project index fresh, 0 stale reads, 0
repairs — and reported "recovered, no restart needed". **doyle falsified it within two minutes**
with two later samples of his own: 11:07Z pump STALLED at 133 s, 11:08Z `serve list` still
`SERVE_UNCONFIRMED`. **A single sample of a monotonic "last tick N s ago" counter cannot separate
STILL TICKING from TICKED ONCE** — the low reading I got is equally consistent with one tick between
two stalls, and I read it as a trend. His rider matters too: the **project index being fresh proves
the COORDINATOR loop, not the pump** — two different loops in one status block, and I let a healthy
one vouch for a sick one.

What stands: check free space BEFORE restarting a stalled daemon on this box, because a restart on a
full disk would "fix" it and mis-teach everyone (the same false confirmation the second face records
for `cargo clean`), and a restart here also risks the #287 shell stranding. What does NOT stand:
"the reclaim fixed the daemon". To claim a pump recovered, sample the counter repeatedly and show it
RESETTING across samples.

Kin: [[test-profile-pool-outgrows-the-disk-floor]], [[free-space-floor-blocks-golden]],
[[a-kill-is-only-as-scoped-as-its-filter]], [[hfenduleam-disk-full-ci]].
