Note: this report was drafted with Claude (Anthropic).
Summary
basecamp vaults download <upload-id> (and basecamp files download) consistently fail with download failed with status 401 against a real OAuth-authenticated session, even though:
- The metadata fetch (
Uploads.Get) succeeds with the same token
- The download endpoint (
/buckets/<bid>/uploads/<id>/download/<filename>) does return a valid 302 with a signed storage.basecamp.com Location when called with the same token via curl
- That signed URL fetched without any
Authorization header returns 200 with the correct binary
So the API is working as the SDK expects (auth'd hop 1 → 302 → unauth'd hop 2 → 200 binary). Something in the SDK's fetchSignedDownload second hop is reporting a 401 even though the same hop works fine when reproduced manually.
Reproduction
$ basecamp upload ./some.pdf --in MyProject
{ "id": <upload-id>, ... }
$ basecamp vaults download <upload-id> --in MyProject -v
[0.403s] Calling Uploads.Download
[0.407s] Calling Uploads.Get
[0.581s] Completed Uploads.Get (174ms)
[0.735s] Failed Uploads.Download: download failed with status 401
{ "ok": false, "error": "download failed with status 401", "code": "api_error" }
The error string "download failed with status %d" only appears at one site in the SDK: go/pkg/basecamp/download.go:38, inside fetchSignedDownload. So the 401 is from the second hop (the signed-URL fetch), not the API.
Environment
- basecamp-cli:
0.7.2 (Homebrew tap basecamp/tap/basecamp-cli)
- macOS: 15.7.5 arm64
- OAuth type:
launchpad
Summary
basecamp vaults download <upload-id>(andbasecamp files download) consistently fail withdownload failed with status 401against a real OAuth-authenticated session, even though:Uploads.Get) succeeds with the same token/buckets/<bid>/uploads/<id>/download/<filename>) does return a valid302with a signedstorage.basecamp.comLocation when called with the same token via curlAuthorizationheader returns200with the correct binarySo the API is working as the SDK expects (auth'd hop 1 → 302 → unauth'd hop 2 → 200 binary). Something in the SDK's
fetchSignedDownloadsecond hop is reporting a 401 even though the same hop works fine when reproduced manually.Reproduction
$ basecamp upload ./some.pdf --in MyProject { "id": <upload-id>, ... } $ basecamp vaults download <upload-id> --in MyProject -v [0.403s] Calling Uploads.Download [0.407s] Calling Uploads.Get [0.581s] Completed Uploads.Get (174ms) [0.735s] Failed Uploads.Download: download failed with status 401 { "ok": false, "error": "download failed with status 401", "code": "api_error" }The error string
"download failed with status %d"only appears at one site in the SDK:go/pkg/basecamp/download.go:38, insidefetchSignedDownload. So the 401 is from the second hop (the signed-URL fetch), not the API.Environment
0.7.2(Homebrew tapbasecamp/tap/basecamp-cli)launchpad