Cursor Troubleshooting
Common issues when building and running the flight booking platform with Cursor, and the exact command or fix for each one.
Setup & Build
| Problem | Solution |
|---|---|
| backend/ or frontend/ missing | In Cursor, run build then ./run.sh. |
| Agent pauses on every cd, npm, or docker-compose command | Cursor Settings → Agent → Terminal → Allowlist (with Sandbox), and allowlist cd, mkdir, npm, ./run.sh, docker, docker-compose, node, lsof. |
| Build wizard doesn't appear, or agent scaffolds without asking config questions | Switch to Plan mode (Shift+Tab), then type build again and confirm when prompted. |
Backend & Credentials
| Problem | Fix |
|---|---|
| Health is OK but hotel search/booking returns 502 or auth errors | TRAVCLAN_API_KEY, TRAVCLAN_USER_ID, or TRAVCLAN_MERCHANT_ID in backend/.env are missing or invalid. Run configure env in Cursor and paste real sandbox keys, then ./run.sh stop && ./run.sh. |
| Browser CORS error | APP_ALLOWED_ORIGINS in backend/.env must include http://localhost:5173. Update and restart with ./run.sh stop && ./run.sh. |
| Backend container exits or health check times out | Run ./run.sh status and cd backend && docker compose logs --tail=50 api. Usually a port conflict, Docker not running, or stale containers. |
| Container name already in use | ./run.sh stop, then cd backend && docker compose down --remove-orphans, then ./run.sh. |
| Filebeat container restarting in a loop | Logging is enabled without Elasticsearch configured. Either set LOGGING_ENABLED=false, or run add elastic server to set it up properly. |
Frontend & Search
| Problem | Fix |
|---|---|
| Connection refused / network error from the browser | frontend/.env must have VITE_API_BASE_URL=http://localhost:8000 (no trailing slash), and the backend must be running. |
| Search returns 200 but the page stays on “Searching flights…” | StrictMode double-invokes useEffect. Do not drop results with a cleanup cancelled flag. Apply the response only when inflight.current still matches the request key. |
| Back from itinerary re-hits search forever | Skip fetch when searchStore.response exists and lastQueryKey matches the current URL query. Retry only bumps a retry counter. |
| Airport dropdown is clipped or empty | No airport API. User must pick from src/data/airports.ts. Do not put overflow-hidden on a parent of the list; dropdown is absolute + z-50. |
| Origin/destination look valid but Search does nothing | Origin ≠ destination. Round-trip: return date ≠ depart date and ≥ 2 calendar days later. Both must be picked IATA codes, not free text. |
| Search/Select/Continue buttons look blank | White-on-white CSS — primary CTAs must use brand/primary color with white text (.btn-primary), even when disabled (opacity-50, still visible). |
| Results show a number with no currency, or the wrong amount | Card price is fF (final fare) with currency cr, via formatMoney(fF, cr). Do not use pF / bF as the main price. |
| Round-trip return list is empty after picking outbound | Domestic: sibling response.results.inboundFlights. International: selected outbound’s nested inboundFlights via nestedInboundOptions(). |
| Selecting a card navigates away / create-itinerary loops | Select only stores rI. Only Continue creates the itinerary. One request per click (createInFlight). Open a new tab with window.open("about:blank") before the POST. |
| Continue does nothing / itinerary tab never opens | Browser blocked the popup. Allow pop-ups, then try again. If window.open returns null, do not POST. |
| Fare rules modal is empty or loops | POST /api/v1/flights/fare-rules with traceId + that card’s rI. Deduplicate with traceId:resultIndex. Search objects do not have a usable fareRule field. |
| Search fails after the app was idle | Supplier errorCode 6 is search-session timeout, not auth. Start a new search from the home page. Message: “This search session has expired…” |
Itinerary, passengers, book
| Problem | Solution |
|---|---|
| Itinerary page has no origin/destination/currency | There is no top-level itinerary origin / destination / currency. Read itineraryItems[].itemFlight and itemFlight.fareQuote.currency. |
| “Continue to reprice” dumps JSON and never leaves passengers | duplicatesFound: true is a warning (HTTP 200). Store duplicateBookings and still go to /flights/reprice. Never JSON.stringify the response in the UI. |
| Reprice never runs / books immediately | Reprice is confirm-fare only. Book only on Confirm and book. One reprice per itineraryCode:traceId; one book per click (bookingRef). |
| Book succeeds but confirmation says no booking code | Do not navigate without bmsBookingCode / bookingCode. If status is FAILED or isSuccessful === false, stay on reprice and show an error. |
| Confirmation route is a bare "→" or empty | Do not use store origin/destination. Parse booking_details.flight_itinerary.responseData.results.itineraryItems[].itemFlight (camelCase itineraryItems). Chain each item’s origin → destination. PNR is on itemFlight.pnr. |
| Amount on confirmation has no currency | Prefer itemFlight.fareQuote.currency + responseData.results.totalAmount via formatMoney. Session store is fallback only. |
Updated 4 days ago
Did this page help you?
