Telegram receipt upload → Inngest "Your server returned HTTP 504 before the SDK responded"
Symptom¶
Uploading a receipt to the Telegram bot surfaces the Inngest error "Your server returned HTTP 504
before the SDK responded" — the receipt pipeline's Inngest function callback into /api/inngest
on Vercel is being killed before it can answer.
Diagnosis (2026-07-21, Records Infrastructure)¶
- The pipeline's heavy work sits in ONE Inngest step,
process-receipt(lib/inngest/receipt-processor.ts~L228): crop (OpenCV/sharp or the remote cropper) + Gemini field-parse + Gemini image-clean + verification — "~10s of pipeline" by its own comment, measured on Pro hardware. - Since the Pro→Hobby downgrade (T-170) the function runs on slower/smaller Hobby compute; the
in-code comment on
/api/inngest(maxDuration: 60 — "60 s on Pro, capped to 10 s on Hobby") suggests the effective window may be as low as 10s. Either way (10s clamp or >60s slow run), the mega-step no longer fits one invocation → Vercel kills it → Inngest reports the 504 → retries → repeated failures surface to the chat. - Not caused by T-169 (the note-prompt change touches only the webhook's prompt messages).
Fix direction (route to a T-NNN if implemented)¶
- Split the mega-step so each Inngest invocation does one phase within its own window:
crop-image→parse-fields(+ keep clean/verify with parse or split further). The image-bytes-through-step-output pattern is already established (the download step returns base64, ≤3MB guarded), so the split doesn't change the output-size profile. - Downscale before OpenCV (sharp already in deps; cropper targets 1200px anyway) to cut CPU on Hobby-class compute.
- Longer-term (T-171 phase 2 alignment): host the cropper (
services/receipt-cropper) — or the whole heavy phase — on the NAS next to the planned pdf-renderer, keeping Vercel functions thin. - Verify the REAL effective duration cap on Hobby (the "10s" comment may be stale — Vercel now allows 60s on Hobby) once runtime evidence is available; update the comment either way.