Troubleshooting: Stuck Spinner After PDF Upload
A customer reports that the order page keeps spinning after upload, even though processing looks like it finished (e.g. Langfuse shows successful extraction traces). Use this guide to find out which half is broken: the extraction, or the poll that is supposed to notice it finished.
Flow summary
Section titled “Flow summary”- Webapp uploads the file → creates a
pdf_documentsrow (statuspending) → starts a Temporal workflow. - temporal-worker runs the extraction activities, writes
extracted_orders, and updatespdf_documents.statustocompleted. - Webapp shows the “Extracting order details…” spinner while
pdf_documents.statusispendingorprocessing. - Frontend polls
GET /api/pdf-documents/{documentId}. When the response hasstatus === 'completed'it stops polling and loads the orders.
So the spinner only stops when the webapp API returns status: 'completed'.
If a customer is stuck spinning, one of these is true:
- The workflow never set
pdf_documents.statustocompleted. - The poll never gets a 200 with
status: 'completed'(a 400/404 keeps the frontend retrying without surfacing an error). - Replication lag, if the webapp reads a replica that the worker’s write hasn’t reached yet.
Diagnostic checklist
Section titled “Diagnostic checklist”1. Check database state
Section titled “1. Check database state”Using the document_id from the customer’s URL or from a Langfuse trace:
SELECT id, status, processing_error, updated_at, clerk_organization_id, user_idFROM pdf_documentsWHERE id = '<document_id>';completedwith a recentupdated_at→ extraction worked. The problem is the poll — go to step 2.pending/processingwith no rows inextracted_orders→ the workflow never ran or died early. Check the Temporal UI for the workflow on this document id, and the temporal-worker logs.pending/processingbut rows exist inextracted_orders→ the activity saved orders but the status update failed. Check temporal-worker logs for the status-update failure (often a DB timeout, or an oversizedoriginal_datapayload).failed→ extraction failed. If the customer still sees only a spinner, the poll is also failing — go to step 2.
2. Why the poll might not return 200
Section titled “2. Why the poll might not return 200”GET /api/pdf-documents/[id] returns 200 only if:
- the user is authenticated (
locals.user); - for non–support-admin users,
locals.organizationis set (otherwise 400); - the document’s
clerk_organization_idmatcheslocals.organization.id(otherwise 404); - the document’s
user_idis null or matches the current user (otherwise 404).
The frontend treats a non-ok response as transient and keeps polling, so the spinner never resolves and no error is shown.
Typical “works for me, not for the customer” causes:
- Organization mismatch — document created under org A, customer is in org B. → 404
- Missing organization in session — personal account, or org not loaded. → 400
- User mismatch —
user_idis set to a different member. → 404
What to check: the route logs a warning on both branches, including
documentId, userId, and organizationId. Search Cloud Logging for
GET pdf-document returned 404 (or returned 400 (no organization)) with the
customer’s document id, then compare against the clerk_organization_id and
user_id in the SQL above.
3. Replication lag
Section titled “3. Replication lag”If the webapp reads a replica while the worker writes the primary, there can be a
short window where the DB says completed but the API still returns the old
status. This is normally seconds, not an infinite spinner — if it persists,
consider reading document status from the primary on the polling endpoint.
Quick fixes for the customer
Section titled “Quick fixes for the customer”- Refresh the page — if the DB already says
completed, a full reload skips polling and renders the orders. - Re-upload — creates a new document if the old row is unrecoverable.
- Check the org — if the cause is an org or user mismatch, confirm they’re in the correct organization.
Code references
Section titled “Code references”- Polling store:
apps/webapp/src/stores/pdfOrder/order.ts - Webapp API:
apps/webapp/src/pages/api/pdf-documents/[id].ts— auth + org + user filter; emits the 404/400 diagnostic warnings referenced above - Extraction activities:
apps/temporal-worker/activities/