Skip to main content

Troubleshooting

Diagnose setup, SSR, authentication, realtime, and upload failures from the boundary inward.

Start with the first boundary that fails. Avoid changing several options at once; that hides the cause.

Module cannot find Convex

Symptom: setup fails with a missing Convex URL, or queries never connect.

  1. Confirm NUXT_PUBLIC_CONVEX_URL exists in the environment running Nuxt.
  2. Confirm it points to the intended .convex.cloud deployment.
  3. Restart Nuxt after changing local environment files.
  4. If the value was added only after a production build, use Nuxt's NUXT_PUBLIC_* runtime override or rebuild.

SSR succeeds but hydration changes the page

Symptom: initial HTML and the hydrated client show different identity or query data.

  • Do not read browser-only state during server rendering.
  • Pass explicit, deterministic query arguments.
  • Keep the same query auth mode on server and client.
  • Use useConvexQuery instead of manually combining a server fetch and a separate client subscription.
  • Check the structured query status and error instead of treating empty data as loading.

Auth proxy fails

Symptom: sign-in returns a proxy or token-exchange error.

Check, in order:

  1. convex.siteUrl or NUXT_PUBLIC_CONVEX_SITE_URL targets the correct HTTP Actions origin.
  2. Better Auth routes are registered in convex/http.ts.
  3. Convex has SITE_URL set to the exact Nuxt origin.
  4. Convex has a strong BETTER_AUTH_SECRET.
  5. The deployment preserves the /api/auth/* Nitro route.
  6. No proxy or CDN rewrites the host, cookies, request bytes, or redirect behavior unexpectedly.

A protected query runs anonymously

auth: 'optional' waits for initial auth settlement but permits anonymous execution. Use auth: 'required' when the call must not run without identity, and still enforce identity inside the Convex handler.

Use auth: 'none' only for intentionally public data. It always uses the dedicated anonymous transport, even while the user is signed in.

Realtime stops updating

  • Verify subscribe was not set to false.
  • Inspect connection state.
  • Check that CSP and the network permit the exact Convex WebSocket origin.
  • Confirm the component still owns the query; subscriptions stop after the last owner leaves.
  • Do not construct a separate raw ConvexClient for the same state.

Errors lose useful detail

Use ConvexCallError fields—kind, code, status, and data—rather than parsing message strings. Run unknown failures through normalizeConvexError. The library intentionally does not expose raw upstream bodies or serialize cause.

Uploads stall

Check file limits before requesting an upload URL, confirm the generated URL has not expired, and watch queue concurrency. A successful storage upload does not automatically create an application record; treat those as two explicit steps and define compensation for the second step failing.

For a minimal reproduction, disable auth only if the failure is unrelated to identity, reduce the page to one explicit query or call, and record the public structured error. Never attach session cookies, bearer tokens, or secrets to an issue.