fix(cli): stop reporting backend upload failures as bad API keys
Draft
PO
2mo ago+61+61+01234567890123456789-61-61-01234567890123456789
Summary
- Who is hurt: users running
capgo bundle uploadare told their API key is bad when the backend hiccups, and every failure opens a new error-tracking issue. The exception fired 126 times across 47 fingerprints from 16 installs in 30 days, still firing on 2026-08-09. - Root cause:
getUserIdFromApikeyreturnednullfor any Postgres failure, not just a missing user. The files service then returned400 user_not_found, so a transient database blip reached the user as a bad key. On the CLI, the flattened error carried no status anduser_not_foundwas not an expected-error marker, so it was reported as a crash. - Some failures are not user errors: on 2026-08-06 a single caller hit six failures in two seconds, each with a well-formed 36-character key — a backend blip, not six bad keys.
Changes
| Layer | Before | After |
|---|---|---|
getUserIdFromApikey | swallows a query failure, returns null | rethrows the failure, so a blip surfaces as 500 |
checkWriteAppAccess | 400 user_not_found | 401 user_not_found, matching invalid_apikey on the same route |
CLI uploadTUS / delta partial.ts | delta path rejects the raw tus blob (leaks URL + per-file object key, no status) | both build a real Error via a shared buildTusUploadError helper carrying status, backend message, and request id |
isExpectedUserError | misses user_not_found | matches it by the attached .status (401) and by a new marker |
A genuine missing user now returns 401 and the CLI treats it as an auth error (no error-tracking issue). A transient database fault now returns 500, so users are no longer told to rotate a valid key.
Merging this fix also cuts a CLI release that carries the earlier merged fixes (#2885, #2933, #2934, #2947) that no released build contains yet.
Test plan
cd cli && bun run typecheck && bun run lint && bun test/test-posthog-exception.mjs— all pass.- Added cases to
test-posthog-exception.mjs: a bareuser_not_foundError and a tus error carrying.status = 401are both classified as expected user errors. oxlintclean on the changed backend files.
Screenshots
Not applicable — CLI error-classification and backend status-code change, no visual surface.
Checklist
- My code follows the code style of this project and passes
bun run lint:backend && bun run lint. - My change requires a change to the documentation.
- I have updated the documentation
accordingly. - My change has adequate E2E test coverage.
- I have tested my code manually, and I have provided steps how to reproduce
my tests
Agent context
- The native build upload path (
cli/src/build/request.ts) has a third copy of the tus-error shaping. It belongs to a different command than this symptom, so it was left untouched to keep the change scoped.
Created with PostHog Desktop from this inbox report.
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.