publish.sh could not upload anything to Garage as merged in #2 — it would have failed on first real use, after passing its whole test suite.
Measured, not inferred
An error occurred (InvalidRequest) when calling the PutObject operation:
Bad request: invalid checksum algorithm
aws-cli/2.34.24. Recent awscli2 attaches a checksum algorithm to every PutObject by default; Garage refuses it.
The expensive part is that it reads as a permissions problem: reads succeed on every bucket, writes fail on every bucket, and it fails identically against one the same credentials are known to be able to write. I only separated the two by testing a bucket I knew was writable.
The fix
AWS_REQUEST_CHECKSUM_CALCULATION=when_required and AWS_RESPONSE_CHECKSUM_VALIDATION=when_required, set inside the script. A caller should not have to know about a client-side default to publish to the object store this tooling exists for, and leaving it to the environment means it works on one machine and not another. when_required keeps checksums where the protocol needs them, which is narrower than switching them off.
The test that would have caught it
An opt-in live round trip — upload, read back byte-for-byte, delete — skipped unless a scratch bucket and credentials are present, so the default offline run is unchanged.
Everything else in this suite proves the command is well formed. That is a different claim from a server accepts it, and this failure lived exactly in the gap.
One trap worth knowing about: the live block captures the real credentials at the top of the file, before the deliberate fakes (AKIAFAKETESTKEY) are exported for the offline tests. Without that it authenticates as the fake and fails every time — and a live test that always fails gets disabled, which is worse than not having one. That cost me a debugging round.
Verified both directions against the real bucket
passed
skipped
failed
offline
9
1
0
live
11
0
0
live, with the fix removed
9
0
2
The third row is the one that matters: the new test genuinely catches the original bug rather than merely passing alongside the fix.
Closes #3.
`publish.sh` could not upload anything to Garage as merged in #2 — it would have failed on first real use, after passing its whole test suite.
## Measured, not inferred
```
An error occurred (InvalidRequest) when calling the PutObject operation:
Bad request: invalid checksum algorithm
```
aws-cli/2.34.24. Recent awscli2 attaches a checksum algorithm to every `PutObject` by default; Garage refuses it.
The expensive part is that **it reads as a permissions problem**: reads succeed on every bucket, writes fail on every bucket, and it fails identically against one the same credentials are known to be able to write. I only separated the two by testing a bucket I knew was writable.
## The fix
`AWS_REQUEST_CHECKSUM_CALCULATION=when_required` and `AWS_RESPONSE_CHECKSUM_VALIDATION=when_required`, set **inside the script**. A caller should not have to know about a client-side default to publish to the object store this tooling exists for, and leaving it to the environment means it works on one machine and not another. `when_required` keeps checksums where the protocol needs them, which is narrower than switching them off.
## The test that would have caught it
An **opt-in live round trip** — upload, read back byte-for-byte, delete — skipped unless a scratch bucket and credentials are present, so the default offline run is unchanged.
Everything else in this suite proves the command is *well formed*. That is a different claim from *a server accepts it*, and this failure lived exactly in the gap.
One trap worth knowing about: the live block captures the real credentials at the **top** of the file, before the deliberate fakes (`AKIAFAKETESTKEY`) are exported for the offline tests. Without that it authenticates as the fake and fails every time — and a live test that always fails gets disabled, which is worse than not having one. That cost me a debugging round.
## Verified both directions against the real bucket
| | passed | skipped | failed |
|---|---|---|---|
| offline | 9 | 1 | 0 |
| live | **11** | 0 | 0 |
| live, with the fix removed | 9 | 0 | **2** |
The third row is the one that matters: the new test genuinely catches the original bug rather than merely passing alongside the fix.
Measured against the real endpoint, not inferred: every PutObject failed
with
An error occurred (InvalidRequest) when calling the PutObject
operation: Bad request: invalid checksum algorithm
on aws-cli/2.34.24. Recent awscli2 attaches a checksum algorithm by
default and Garage refuses it, so publish.sh could not upload anything --
after passing its entire test suite.
It also reads as a permissions problem, which is the expensive part: reads
succeed, writes fail, and it fails identically against a bucket the same
credentials demonstrably can write. Set here rather than documented,
because a caller should not need to know a client-side default to publish
to the object store this script exists for, and leaving it to the
environment makes it work on one machine and not another.
`when_required` keeps checksums where the protocol needs them, so this is
narrower than switching them off.
Adds the test that would have caught it: an opt-in live round trip that
uploads, reads back and deletes, skipped unless a scratch bucket and
credentials are present so the offline run is unchanged. Everything else in
this suite proves the command is well formed, which is a different claim
from a server accepting it, and this failure lived exactly in that gap.
The live block captures the real credentials at the top of the file,
before the deliberate fakes (AKIAFAKETESTKEY) are exported for the offline
tests -- otherwise it authenticates as the fake and fails every time, and a
live test that always fails gets disabled, which is worse than not having
one.
Verified both directions against the real bucket: with the fix, 11 passed /
0 skipped; with it removed, the two live assertions fail. Offline, 9 passed
/ 1 skipped.
Closes#3.
Co-authored-by: bit <bit@das-labor.org>
claude
merged commit fcc6a741ef into main2026-09-09 06:59:04 +00:00
claude
deleted branch fix/garage-checksum2026-09-09 06:59:05 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #3.
publish.shcould not upload anything to Garage as merged in #2 — it would have failed on first real use, after passing its whole test suite.Measured, not inferred
aws-cli/2.34.24. Recent awscli2 attaches a checksum algorithm to every
PutObjectby default; Garage refuses it.The expensive part is that it reads as a permissions problem: reads succeed on every bucket, writes fail on every bucket, and it fails identically against one the same credentials are known to be able to write. I only separated the two by testing a bucket I knew was writable.
The fix
AWS_REQUEST_CHECKSUM_CALCULATION=when_requiredandAWS_RESPONSE_CHECKSUM_VALIDATION=when_required, set inside the script. A caller should not have to know about a client-side default to publish to the object store this tooling exists for, and leaving it to the environment means it works on one machine and not another.when_requiredkeeps checksums where the protocol needs them, which is narrower than switching them off.The test that would have caught it
An opt-in live round trip — upload, read back byte-for-byte, delete — skipped unless a scratch bucket and credentials are present, so the default offline run is unchanged.
Everything else in this suite proves the command is well formed. That is a different claim from a server accepts it, and this failure lived exactly in the gap.
One trap worth knowing about: the live block captures the real credentials at the top of the file, before the deliberate fakes (
AKIAFAKETESTKEY) are exported for the offline tests. Without that it authenticates as the fake and fails every time — and a live test that always fails gets disabled, which is worse than not having one. That cost me a debugging round.Verified both directions against the real bucket
The third row is the one that matters: the new test genuinely catches the original bug rather than merely passing alongside the fix.
Measured against the real endpoint, not inferred: every PutObject failed with An error occurred (InvalidRequest) when calling the PutObject operation: Bad request: invalid checksum algorithm on aws-cli/2.34.24. Recent awscli2 attaches a checksum algorithm by default and Garage refuses it, so publish.sh could not upload anything -- after passing its entire test suite. It also reads as a permissions problem, which is the expensive part: reads succeed, writes fail, and it fails identically against a bucket the same credentials demonstrably can write. Set here rather than documented, because a caller should not need to know a client-side default to publish to the object store this script exists for, and leaving it to the environment makes it work on one machine and not another. `when_required` keeps checksums where the protocol needs them, so this is narrower than switching them off. Adds the test that would have caught it: an opt-in live round trip that uploads, reads back and deletes, skipped unless a scratch bucket and credentials are present so the offline run is unchanged. Everything else in this suite proves the command is well formed, which is a different claim from a server accepting it, and this failure lived exactly in that gap. The live block captures the real credentials at the top of the file, before the deliberate fakes (AKIAFAKETESTKEY) are exported for the offline tests -- otherwise it authenticates as the fake and fails every time, and a live test that always fails gets disabled, which is worse than not having one. Verified both directions against the real bucket: with the fix, 11 passed / 0 skipped; with it removed, the two live assertions fail. Offline, 9 passed / 1 skipped. Closes #3. Co-authored-by: bit <bit@das-labor.org>