Troubleshooting
Grouped by what you see, with the exact text the relay returns.
I sent a request and nothing appeared in the log
Three causes, in order of likelihood:
- The endpoint runs in Tunneling with save off. Tunneling forwards without recording unless Save full request & response is on (it is on by default). Stop the endpoint and start it again with that checkbox enabled if you want both.
- The list has not caught up yet. It polls every few seconds; Refresh above the list fetches immediately.
- The request never arrived. Run the request with
curl -iand read the status. A recorded request always returns something from the relay, so a connection error means it did not reach us at all.
I get 204 No Content and my local service sees nothing
That is Logging working as designed: the relay records the request and answers
204 without forwarding. Restart the endpoint in Tunneling to reach your
machine.
I get 503 No agent for client
The relay has no live HTTP agent for that host. Any of these produce it:
- the desktop app or the npm CLI is not running, or is signed out / unauthenticated
- the app lost its network, and the claim lapsed after 15 seconds without a heartbeat
- the endpoint was started but the agent has not registered yet — wait a moment and retry
- the hostname does not match an endpoint, usually a typo in the subdomain
- the endpoint speaks a different protocol than the request, for example plain HTTP or Socket.IO polling sent to a WebSocket endpoint
The body is text/plain with no Access-Control-Allow-Origin. A browser
XHR from another origin reports this as CORS. Confirm with curl:
curl -i https://your-endpoint.mercur.sh/socket.io/?EIO=4&transport=pollingThe browser reports CORS, curl shows 503
Cross-origin XMLHttpRequest (including Socket.IO transport=polling) requires
Access-Control-Allow-Origin on the response. Mercur 503, 502, 403, and
429 replies do not include CORS headers, so Chrome reports a CORS failure
even when the relay answered with a clear error body.
Default Socket.IO starts with HTTP polling to /socket.io/, then tries
WebSocket upgrade. Mercur HTTP endpoints forward GET/POST and do not proxy
upgrade. Mercur WebSocket endpoints accept upgrade and do not serve
polling. Polling a WebSocket endpoint is HTTP on a WS host, which is the
wrong-protocol case of 503 No agent for client above.
If curl returns Engine.IO JSON and the browser still fails CORS, the page
origin (for example http://localhost:63342) is not in the local Socket.IO
cors.origin list. Allow that origin, or serve the HTML through the same
tunnel so the request is same-origin. transports: ["websocket"] only helps
on a WebSocket endpoint.
The HTTP agent buffers the full upstream body. Socket.IO long-poll through an HTTP tunnel stays a poor fit even after CORS is correct.
Walkthrough: Inspect a WebSocket session. Release notes: Inspect WebSocket traffic on a localhost tunnel.
I get 503 Server is not running
The endpoint exists but is stopped, starting, or failed. Open it in the console and press Enable. Seeing this immediately after enabling is normal for a moment, while the agent registers.
I get 403 Forbidden
The endpoint is not public and your address is not on its list. Add the caller's address
to the IP whitelist, or set Public access to true. Remember that the caller is
often not you — a webhook provider calls from its own ranges.
I get 429
You reached the monthly request quota for your plan and the body says Monthly HTTP request quota exceeded. Quotas reset monthly; see limits.
I get 503 Too many concurrent sessions
More connections were open at once than your plan allows. In-flight requests finish and free the slots. Long-lived requests hold a slot for their whole duration, so a slow endpoint reaches this sooner.
I get 502 with connect ECONNREFUSED 127.0.0.1:3000
The relay reached your machine and your machine refused the connection. Your local process
is not listening, or is listening on a different port than the one you entered when you
started Tunneling.
Check with curl -i localhost:3000 first — if that fails, the problem is entirely local.
Longer walkthrough: Webhook 502 localhost. Port conventions for Next.js (3000) vs Uvicorn/Django (8000): framework webhook localhost.
I get 502 Bad Gateway with no detail
The connection between the relay and your agent failed mid-request. Stop and start the endpoint, then retry.
Connections tab is empty
The Connections tab exists only on WebSocket endpoints. An HTTP endpoint shows request history instead. If the endpoint is WebSocket and the list stays empty:
- the agent is not claimed (same causes as
503 No agent for client) - no public client completed Upgrade
- you are looking at a share link that expired
Failed handshakes can still appear as state: error. How-to:
Inspect a WebSocket session.
My WebSocket or TCP connection is dropped without an error
Rejections before a WebSocket handshake completes close the socket without an HTTP
response, so a client only reports a reset connection. The causes are the same as the HTTP
list above: unknown host, stopped endpoint, address not allowed, no agent, quota, or
session limit. Check the endpoint in the console. On a WebSocket endpoint, an error
row on the Connections tab is the inspectable form of that failure.
WebSocket and TCP also require a plan that includes them. Solo and Team include both; Guest and Free stay HTTP-only. See limits.
The console will not let me run the endpoint
Endpoint is in use by <hostname>— another machine holds this endpoint. Stop it there first.Running this mode requires the Electron app with a connected device agent— forwarding from the browser is refused; use the desktop app or the npm CLI. The browser can run Logging only.Endpoint must be stopped before changing its run mode— stop it, then start it in the mode you want.Device agent credential is invalid— sign in again in the desktop app, or runmercur authagain with a valid CLI token, so the machine registers anew.
The CLI will not start a tunnel
No CLI token found— HTTP still works without an account:npx @mercur_dev/cli http 3000. For a workspace, create a token under Settings → CLI tokens (pick a workspace) and runmercur auth, or setMERCUR_TOKENin CI. Tokens start withmcrcli_. Customer-scoped tokens minted before this change no longer work.- Occupied endpoint — the desktop app or another CLI already holds it. Stop it there, or wait for a crashed holder's heartbeat to expire.
- Wrong console — a token created on a local console will not work against production.
Set
MERCUR_API_URLif you are not usinghttps://console.mercur.sh.
Walkthrough: CLI agent.
A response body is missing from a recorded request
Response recording is a separate setting from request recording, and it only applies in Tunneling. Enable Save full request & response when starting the endpoint. Logging never has a response to store, because nothing is forwarded.
Old requests disappeared
Each plan caps how many requests an endpoint keeps, and the oldest are dropped past the cap. Everything is deleted 30 days after arrival regardless. See limits.