Skip to main content

Delivery Marketplace Troubleshooting Runbook

Operational runbook for diagnosing PedidosYa connection, webhook ingest, menu sync, and outbound order-action failures in apps/backend/src/delivery-marketplace/.

Pair with Delivery Marketplace Architecture.


Scope

Primary codepaths:

  • application/use-cases/connect-marketplace.use-case.ts
  • application/use-cases/ingest-marketplace-order.use-case.ts
  • application/marketplace-provider-registry.service.ts
  • interfaces/delivery-marketplace.controller.ts
  • interfaces/webhooks/pedidosya-plugin.controller.ts
  • interfaces/guards/pedidosya-ip-allowlist.guard.ts
  • infrastructure/pedidosya/*
  • infrastructure/processors/marketplace-*.processor.ts

Runtime provider matrix:

ProviderRegistered adapter
pedidosyaPedidosYaAdapter
uber_eatsnone — MarketplaceProviderNotConfiguredError

1) Symptom triage

SymptomLikely layer
Connect returns Unknown/not configured errorMarketplaceProviderRegistry (e.g. uber_eats)
Connect returns 422 Invalid credentials or store not foundAdapter testConnection / wrong store id or credentials
Connect returns 409 already existsNon-disconnected connection for location+provider
Webhook returns 401 IP not in PedidosYa allowlistPEDIDOSYA_WEBHOOK_IP_ALLOWLIST / proxy IP forwarding
Webhook returns 400 Invalid order payloadPedidosYa Zod schema mismatch
Ingest logs "No active connection" and returns 200Missing/inactive connection for store_id
Ingested order stuck in pending_sessionNo open cash register session at connection location
Ingested order status error / "Missing menu mappings"Menu never pushed or mapping incomplete
Menu push returns 409 already in progressRedis lock marketplace:menu-push-lock:{connectionId}
Accept returns 400 wrong statusOrder not in received / pending_session
Item availability 404 No marketplace mappingProduct not in menu mappings; run menu push
Provider never sees acceptOutbound BullMQ job failing / credentials decrypt / acceptance window
Duplicate webhook ignoredExpected dedup via insertIfNew

2) Connection checks

Expected connect flow:

  1. Authenticated POST /delivery-marketplace/connections?businessId=...
  2. Credential test against PedidosYa
  3. Encrypt credentials, persist connection as active

Verify:

  1. provider is pedidosya (not reserved uber_eats).
  2. externalStoreId matches the PedidosYa vendor / store id used in webhooks (payload.client.store_id).
  3. externalChainId is set when the PedidosYa account is chain-scoped.
  4. After disconnect (DELETE), reconnect is allowed; an active duplicate is not.

Test an existing connection with POST /delivery-marketplace/connections/:id/test?businessId=....


3) Webhook and ingest checks

Public routes under /marketplace/pedidosya:

  1. Confirm Cloud Run / reverse proxy preserves client IP or sets X-Forwarded-For correctly when the allowlist is enabled.
  2. Hit GET /marketplace/pedidosya/health for reachability.
  3. For order dispatch failures, inspect backend logs around PedidosYaPluginController and IngestMarketplaceOrderUseCase.
  4. Confirm a connection exists for the webhook store_id + pedidosya.
  5. If webhookSecret is set on the connection, ingest requires a matching token parameter — the PedidosYa controller currently does not supply one. Leave webhookSecret unset for PedidosYa unless token forwarding is implemented; rely on IP allowlisting.

Ingest outcome statuses to look for:

StatusMeaning
received → POS createdHappy path before/without accept
pending_sessionNo open cash register session
errorMapping failure or POS create failure
(no new row)Duplicate external order id

Also inspect GET /delivery-marketplace/connections/:id/sync-log.


4) Menu push and 86

  1. Enqueue with POST .../menu/push. Expect 202/accepted with jobId menu-push:{connectionId}.
  2. On 409, either wait for the Redis lock TTL (180s) or retry with force: true after confirming no healthy worker is mid-push.
  3. Confirm BullMQ workers for marketplace-push-menu are running against the same Redis as the API.
  4. For 86 failures, call GET /delivery-marketplace/connections/:id/menu-mappings and ensure the FlowPOS product id exists as entity type item.
  5. Remember the request body field externalItemId must be the FlowPOS product UUID despite the name.

5) Outbound accept / deny / status

Outbound work runs on queue marketplace-outbound-order-action.

  1. Manual accept enqueues accept:manual:{ingestedOrderId} with no delay.
  2. Auto-accept from ingest uses job id accept:{ingestedOrderId} and delays by defaultPrepTimeMinutes minutes. If PedidosYa rejects accepts as past the acceptance window, disable auto-accept or reduce that delay and retest.
  3. Decrypt failures in the processor surface as job failures; check ENCRYPTION_KEY consistency across instances.
  4. Repeated auth failures can mark connection health degraded — inspect connection lastError* fields and Sentry for the processor.

Kitchen → marketplace status fan-out depends on MarketplaceOrderLifecycleListener. If POS kitchen updates never reach PedidosYa:

  1. Confirm the restaurant order has a linked ingested marketplace order.
  2. Confirm outbound queue processing is healthy.
  3. Confirm status mapper supports the kitchen state being emitted.

6) FEL after marketplace ingest

Successful ingest enqueues marketplace-fel-retry with job id fel:{ingestedOrderId}.

If invoices are missing:

  1. Confirm FEL is configured for the business/location.
  2. Inspect failed jobs on marketplace-fel-retry.
  3. Use existing FEL runbooks under apps/docs/docs/dev/fel/ for certifier / network failures; marketplace only schedules the retry worker.

7) Quick recovery checklist

  1. Provider registered? (pedidosya only today)
  2. Connection active for the webhook store id?
  3. Open cash register session at the location?
  4. Menu mappings present for ordered items?
  5. Redis + BullMQ workers up for all three marketplace queues?
  6. IP allowlist correct in staging/production?
  7. Auto-accept delay compatible with provider SLA?