Found while implementing #10495 (PR #10796). Filing rather than folding in: that card's surface is the reachability report, and this is a separate failure of the same script's write ordering.
The shape
scripts/bump-objectui.sh writes the pin file before it reads anything else about the commit:
echo"$NEW_SHA">"${FRAMEWORK_ROOT}/.objectui-sha"echo"→ objectui pin: ${OLD_SHA:0:12} → ${NEW_SHA:0:12}"
SHORT="${NEW_SHA:0:12}"
SUBJECT_LINE="$(git -C "$OBJECTUI_ROOT" log -1 --format=%s "$NEW_SHA")"If the commit object is not present in the objectui checkout, git log fails, set -e kills the script — and .objectui-sha has already been rewritten. Measured on a throwaway objectui whose HEAD commit object was deleted (git 2.43.0):
→ objectui pin: 30443811f7be → 15a289fc7a87 (reachability UNKNOWN)
fatal: bad object 15a289fc7a87fc825afef8a33f2a2370f519ebd5
SCRIPT EXIT=128
The operator is left with a modified .objectui-sha in the working tree, no changeset, no commit, and a bare fatal: bad object as the whole explanation. Re-running does not self-correct: the pin file now holds the bad SHA, so the next run compares against it.
Why the default path can reach it
This is not only the explicit-argument case. Measured, git 2.43.0: git rev-parse HEAD exits 0 and prints the sha even when that commit object is missing from the object store — it resolves the ref without reading the object. So a plain bump-objectui.sh with no argument can carry an unreadable SHA all the way to the pin write. (A partial clone with the object not fetched, or an interrupted/corrupt object store, gets there.)
PR #10796 makes the reachability half of this loud — it reports "COULD NOT DETERMINE … the commit object is NOT PRESENT" before the write — so the run is no longer silent about it. It deliberately does not change the write ordering or the exit behaviour, which is what this card is for.
Likely shape of a fix
Read what the bump needs from the commit (at minimum SUBJECT_LINE) before the first mutation of .objectui-sha, so an unreadable commit fails with the script's own message and an untouched working tree. Whether an absent object should be a hard refusal rather than a warning is a judgement for triage; #10495's ruling (warning, not gate) was about a non-main pin, not about a pin nobody can read.
Generated by Claude Code
Generated by Claude Code
Found while implementing #10495 (PR #10796). Filing rather than folding in: that card's surface is the reachability report, and this is a separate failure of the same script's write ordering.
The shape
scripts/bump-objectui.shwrites the pin file before it reads anything else about the commit:If the commit object is not present in the objectui checkout,
git logfails,set -ekills the script — and.objectui-shahas already been rewritten. Measured on a throwaway objectui whose HEAD commit object was deleted (git 2.43.0):The operator is left with a modified
.objectui-shain the working tree, no changeset, no commit, and a barefatal: bad objectas the whole explanation. Re-running does not self-correct: the pin file now holds the bad SHA, so the next run compares against it.Why the default path can reach it
This is not only the explicit-argument case. Measured, git 2.43.0:
git rev-parse HEADexits 0 and prints the sha even when that commit object is missing from the object store — it resolves the ref without reading the object. So a plainbump-objectui.shwith no argument can carry an unreadable SHA all the way to the pin write. (A partial clone with the object not fetched, or an interrupted/corrupt object store, gets there.)PR #10796 makes the reachability half of this loud — it reports "COULD NOT DETERMINE … the commit object is NOT PRESENT" before the write — so the run is no longer silent about it. It deliberately does not change the write ordering or the exit behaviour, which is what this card is for.
Likely shape of a fix
Read what the bump needs from the commit (at minimum
SUBJECT_LINE) before the first mutation of.objectui-sha, so an unreadable commit fails with the script's own message and an untouched working tree. Whether an absent object should be a hard refusal rather than a warning is a judgement for triage; #10495's ruling (warning, not gate) was about a non-main pin, not about a pin nobody can read.Generated by Claude Code
Generated by Claude Code