coder/code-server · error · HttpError
Unauthorized
Error message
Unauthorized
What it means
The domain proxy route (domainProxy.ts:94) checks authentication for non-login requests. If the user is not authenticated and the path is not /login (which is allowed through), it throws HttpError 401 instead of proxying. This prevents unauthenticated users from reaching proxied ports via the domain-based proxy.
Source
Thrown at src/node/routes/domainProxy.ts:94
// Assume anything that explicitly accepts text/html is a user browsing a
// page (as opposed to an xhr request). Don't use `req.accepts()` since
// *every* request that I've seen (in Firefox and Chromium at least)
// includes `*/*` making it always truthy. Even for css/javascript.
if (req.headers.accept && req.headers.accept.includes("text/html")) {
// Let the login through.
if (/\/login\/?/.test(req.path)) {
return next()
}
// Redirect all other pages to the login.
const to = self(req)
return redirect(req, res, "login", {
to: to !== "/" ? to : undefined,
})
}
// Everything else gets an unauthorized message.
throw new HttpError("Unauthorized", HttpCode.Unauthorized)
}
proxy.web(req, res, {
ignorePath: true,
target: `http://0.0.0.0:${port}${req.originalUrl}`,
})
})
export const wsRouter = WsRouter()
wsRouter.ws(/.*/, async (req, _, next) => {
const port = maybeProxy(req)
if (!port) {
return next()
}
ensureProxyEnabled(req)
ensureOrigin(req)View on GitHub (pinned to 51f90a376b)
Solutions
- Authenticate at code-server's /login first to obtain a valid session cookie
- Ensure the proxied app shares/sends the code-server session cookie
- For automated clients, perform the login flow then reuse the cookie for proxy requests
Example fix
// before
fetch('https://3000--user.host/proxied-path') // 401
// after
await login('https://user.host/login', password)
fetch('https://3000--user.host/proxied-path') // session cookie sent Defensive patterns
Strategy: try-catch
Validate before calling
// For API clients: ensure a valid session before proxy calls
async function ensureLoggedIn(): Promise<void> {
const r = await fetch("/api/status")
if (r.status === 401) throw new Error("Not authenticated for domain proxy")
} Type guard
import { HttpError, HttpCode } from "../../common/http"
function isProxyUnauthorized(e: unknown): boolean {
return e instanceof HttpError && e.status === HttpCode.Unauthorized
} Try / catch
try {
// proxied request
} catch (e) {
if (isProxyUnauthorized(e)) {
window.location.href = `/login?to=${encodeURIComponent(window.location.href)}`
} else throw e
} Prevention
- Authenticate once and reuse the session cookie for all proxied subdomains
- Handle 401 in proxied-app clients by redirecting to code-server /login
- Avoid putting proxied apps in iframes without sharing the session cookie
When it happens
Trigger: A request to a subdomain proxy URL (e.g. port-3000.codomain) without a valid session cookie and not targeting /login.
Common situations: Sessions expired while a proxied app tab was open; embedding a proxied app in another page with no cookie; race at startup where the proxied app loads before login completes.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of coder/code-server@51f90a376b (2026-08-12).
Data as JSON: /api/errors/e31ff36ff16ce26d.
Report an issue: GitHub.