Start with serve doctor. It checks your account, the relay, and whether your network lets QUIC out over UDP 443, which is the single most common blocker.
The 18 error codes, at a glance
Every refused call returns an envelope with a machine-readable code. Agents should branch on code, not prose. Recovery per code:
| Code | Meaning | What to do |
|---|
tunnel_limit | At the concurrent live-tunnel cap (Free 3 / Pro 10) | Stop a tunnel or serve release <label> a stale link; nothing is evicted |
unknown_subdomain | Subdomain does not exist or is not yours | Check the label with links / serve links; request an existing owned label |
label_taken_suffixed | Even auto-suffixing found no free label | Try a different name |
pro_required | Operation needs Pro | Upgrade at /billing in the console, or via POST /v1/billing/checkout |
udp_blocked | Outbound UDP 443 (QUIC) is blocked | Fix the network/firewall; run serve doctor to confirm |
unauthorized | Token missing, expired, or revoked | serve login again; check the Devices list in the console |
relay_unreachable | Relay edge unreachable | Check connectivity; retry; serve doctor |
internal_error | Internal failure | Retry; if persistent, report to serve@servelink.cc |
port_in_use | Local port already tunnelled | Stop the existing tunnel on that port first |
ambiguous_target | Ambiguous arguments | Pass exactly one of port (a running server) or path (a local file/dir) |
residency_unsupported | The residency value is not supported for this operation | Omit residency / pass the supported value, or use the residency-appropriate tool |
residency_conflict | Label is publishing an artifact | Pass replace=true (Pro) or unpublish first (stop_remote) |
size_cap_exceeded | Publish exceeds the per-deployment cap (Free 100 MB / Pro 1 GB) | Reduce the artifact or upgrade |
publish_rate_limited | Hourly/daily publish budget exhausted | Wait for the reset; every attempt counts, including republish |
storage_cap_exceeded | Total storage cap reached (Free 1 GB / Pro 50 GB) | Unpublish something or upgrade |
transfer_limit | Monthly live-tunnel transfer reached (Free 2 GB / Pro 25 GB) | Wait for the UTC-month reset; the error carries the exact reset time |
relay_egress_limit | Global relay egress limit for the month reached | Retry after reset; nothing of yours is deleted |
not_remote | Target label is not remote-resident | Check residency with links / serve links |
Account and login
`unauthorized` / `401` Your api_token is missing, expired, or revoked. Run serve login again, or check the device list in the dashboard. serve whoami will tell you which of "not logged in", "token revoked", and "service unreachable" you're hitting.
"No relay configured" A logged-in install always has one. Run serve login to write the relay binding, or set SERVE_RELAY.
A live link is up but doesn't work
The URL returns 502 The relay can't reach your local server. Confirm it's actually listening on the port you passed — curl http://localhost:3000 should work locally first.
The URL returns 404 Nothing is bound to that subdomain. Either it never connected, or it dropped and hasn't re-registered. Restart serve.
The page loads but content stays on `Loading…` If this happens in production preview, it's an application defect and no tunnel or HMR change will fix it. See Preview modes.
Published links (remote artifacts)
These are different failures from live-tunnel problems: the bytes are in serve's storage, not on your machine.
The link works even though my machine is off That's expected. Once a publish commits, the artifact serves from serve's storage with no machine attached. An offline source is only a problem for live links.
A publish fails with `size_cap_exceeded` or `storage_cap_exceeded` The deployment exceeds the plan's per-publish cap (Free 100 MB, Pro 1 GB) or the account's current storage cap (Free 1 GB, Pro 50 GB). Unpublish something you don't need (serve remote stop <label>) or upgrade to raise both caps.
A publish fails with `publish_rate_limited` The plan's publish budget is exhausted (Free 30/hour and 100/day, Pro 300/hour and 1,000/day). Every initialized attempt counts, including republish and failed attempts; retry after the hour or day resets.
`serve release <label>` fails with `remote_link` The label still has a published artifact on it. Unpublish first (serve remote stop <label>), then release the link if you no longer want it.
WebSockets
It opens, then closes immediately, over and over (dev mode) Your dev framework rejected the preserved public Origin. Add your exact serve hostname to its dev-origin allowlist — allowedDevOrigins for Next.js — and restart. See Mode B.
It gets a 502 before it ever opens Localhost refused the connection outright. Check the application's origin policy and the port you passed. The full table of pre-101 status codes is in Preview modes.
Network and transport
A QUIC dial fails on the TLS handshake or ALPN The client connects over UDP 443 with ALPN serve-tunnel/2. A handshake failure usually means something on your network interferes with UDP 443, or your client and the relay are on different transport versions. There is no fallback path by design, so upgrade both together.
A QUIC dial times out UDP 443 is likely filtered by a network or host firewall, or your ISP blocks outbound UDP. This is the most common corporate-network problem. serve doctor confirms it.
Limits
A new tunnel fails with `tunnel_limit` You can run 3 simultaneous live tunnels on Free and 10 on Pro. The links themselves are unlimited and are never recycled to make room, so a new tunnel at the cap is simply refused rather than displacing anything. Stop one you don't need, or serve release <label> a stale link.
A request fails with `transfer_limit` or a `503` You've reached your monthly transfer allowance (2 GB on Free, 25 GB on Pro), or the service hit its global transfer ceiling. Both reset at the start of the UTC month, and the error carries the exact reset time. Nothing is deleted when you hit a limit — links stay yours.
Still stuck? Contact serve@servelink.cc with serve doctor and serve --version output. Abuse reports go to abuse@servelink.cc.