Troubleshooting
Most BugPort issues come down to one of a few root causes: a misconfigured auth provider, a widget pointed at the wrong API base, an origin that isn't on an allowed list, or capture limits in the browser. This guide is grouped by area. For each problem you'll find the symptom you'd actually observe, the likely cause, the fix, and a related doc to go deeper.
Read the symptom that matches what you see, not the one that matches what you think is wrong. A "404" and a "403" from the widget have completely different causes โ the status code is the fastest clue.
Authentication & sign-inโ
Social login fails or loops back to sign-inโ
Likely cause: The OAuth provider isn't enabled in Supabase, or the Supabase redirect allowlist doesn't include your origin's /auth/callback URL. Supabase rejects the redirect, so the session is never established.
Fix: In Supabase Auth, enable the Google and/or GitHub provider you're using, and add your origin's /auth/callback to the redirect allowlist (do this for every domain โ local, staging, production). Then retry the sign-in flow.
Related: Security & Privacy
Signed in but no workspace / stuck on onboardingโ
Likely cause: New accounts go through onboarding to create their first workspace. Until that completes, there's no workspace to scope API calls to.
Fix: Finish onboarding to create a workspace. After that, dashboard requests resolve against that workspace.
Related: Getting started โ Create a project
Widget setupโ
Widget submissions rejected with 403 / origin rejectedโ
Likely cause: Widget keys are origin-restricted. The origin the widget is running on isn't in the key's allowed-origins list, so the API refuses the submission.
Fix: Add the exact origin (scheme + host + port) to the widget key's allowed origins in the dashboard. Use a key created for the matching environment (local / staging / production).
Related: NPM widget
Widget requests return 404โ
Likely cause: apiBaseUrl doesn't resolve to a BugPort API base ending in /v1. A base without the version prefix hits a non-existent path.
Fix: Set apiBaseUrl so it ends in /v1 โ the default is https://api.bugport.dev/v1. Only override it for local or self-hosted setups, and keep the /v1 suffix.
Related: NPM widget
Widget renders nothingโ
Likely cause: The widget requires React 18+ and a client-side mount. On older React, or when rendered only on the server, the component never mounts.
Fix: Upgrade to React 18 or later and ensure the widget mounts on the client (see the SSR note under React rendering). Confirm projectKey (the bp_pub_โฆ key, also accepted as publicKey) is passed and required props are present.
Related: NPM widget
Browser extension captureโ
Extension installed but capture doesn't startโ
Likely cause: Not signed in, or the extension isn't pinned/opened on the page you're reproducing on. Capture only runs after you sign in and click start.
Fix: Sign in to the extension, pin it, open it on the target page, click start capture, reproduce the issue, annotate, add details, then submit. The report then appears in the dashboard.
Related: Browser extension
Some network detail or replay is missingโ
Likely cause: Advanced capture options (network detail level, session replay) are collapsed by default and may be off.
Fix: Open the extension's advanced settings and raise the network detail level or enable replay before capturing.
Related: Browser extension
Network / response body captureโ
No response bodies appear in a reportโ
Likely cause: Either the extension is out of date, or the responses are opaque, cross-origin, or binary โ which the browser cannot expose, so they can't be captured. The widget never captures network bodies at all.
Fix: Update the extension to the latest version. Confirm the requests you expect are same-origin and text-based; opaque/cross-origin/binary responses are a hard browser limitation, not a bug. Use the extension (not the widget) when you need network capture.
Related: Bug reports
Captured headers look strippedโ
Likely cause: This is intentional. Sensitive headers are filtered and redaction is applied during capture, so authorization-style headers won't appear verbatim.
Fix: No action needed โ this is the privacy behavior. If you need a value to debug, reproduce it in a way that doesn't rely on a filtered header being stored.
Related: Security & Privacy
API configurationโ
Requests work locally but fail in production (or vice versa)โ
Likely cause: The apiBaseUrl or the credential is environment-mismatched โ e.g. a local widget key used against the production API, or a base URL missing /v1.
Fix: Match the credential to the environment and confirm the base URL ends in /v1. Dashboard/app requests use a Supabase session JWT as a Bearer token; widget submissions use the bp_pub_โฆ key; MCP access uses a scoped MCP token. Check GET /v1/health and GET /v1/version to confirm you're reaching the API.
Related: API overview
Dashboard visibilityโ
A submitted bug isn't visible in the dashboardโ
Likely cause: You're viewing the wrong workspace or project scope. The API is always workspace-scoped, so a bug filed into one project won't show in another's view.
Fix: Switch to the workspace and project the report was filed under. Confirm the widget key or extension was pointed at the intended project/environment, since that determines where the bug lands.
Related: Dashboard
A widget report shows no screenshot but looks "empty"โ
Likely cause: Widget reports without a screenshot are expected โ they render annotations, page path, and feedback. There is no broken image panel by design.
Fix: No action needed. If you want screenshots, prompt reporters to include the optional screenshot, or use the extension which captures one.
Related: Bug reports
React renderingโ
Next.js / SSR hydration mismatch or blank widgetโ
Likely cause: The widget is a client-side React component (React 18+). Rendering it during server-side rendering causes a hydration mismatch or a component that never mounts.
Fix: Mount the widget client-side only. In Next.js, render it in a client component (or dynamically import it with SSR disabled) so it initializes in the browser.
Related: NPM widget
Allowed originsโ
"Origin not allowed" even after adding the domainโ
Likely cause: The allowed-origins entry doesn't exactly match the request origin. Origins are scheme + host + port, so http vs https, localhost vs 127.0.0.1, or a non-default port will mismatch.
Fix: Add the exact origin the browser sends, including scheme and any non-standard port. Add a separate entry for each environment rather than expecting one to cover all. Rotate the key if it may have leaked.
Related: Security & Privacy
Local developmentโ
Widget can't reach the API during local devโ
Likely cause: apiBaseUrl still points at the hosted API, or the local origin isn't in the widget key's allowed origins.
Fix: Point the widget at your local API base โ typically http://localhost:8000/v1 โ keeping the /v1 suffix. Use a local environment widget key and add your local origin (e.g. http://localhost:3000) to its allowed origins.
Related: Getting started โ Quickstart
Still stuck? Capture the exact symptom โ the HTTP status code, the failing origin, and whether you're using the widget, extension, dashboard, or MCP โ then check the Security & Privacy page for how scoping works, and the API overview for auth modes. Most reports resolve once the status code and credential type are pinned down.