Skip to content

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)

  1. Split the mega-step so each Inngest invocation does one phase within its own window: crop-imageparse-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.
  2. Downscale before OpenCV (sharp already in deps; cropper targets 1200px anyway) to cut CPU on Hobby-class compute.
  3. 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.
  4. 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.