coder/code-server · error · HttpError

Unauthorized

Error message

Unauthorized

What it means

Thrown by the proxy() handler when the request is not authenticated and the path is not the proxy root (i.e. req.params.path exists and is not '/'). It is an HttpError with status 401 (HttpCode.Unauthorized). For root paths the handler instead redirects unauthenticated users to the login page; this throw is specifically for non-root unauthenticated access.

Source

Thrown at src/node/routes/pathProxy.ts:44

  res: Response,
  opts?: {
    passthroughPath?: boolean
    proxyBasePath?: string
  },
): Promise<void> {
  ensureProxyEnabled(req)

  if (req.method === "OPTIONS" && req.args["skip-auth-preflight"]) {
    // Allow preflight requests with `skip-auth-preflight` flag
  } else if (!(await authenticated(req))) {
    // If visiting the root (/:port only) redirect to the login page.
    if (!req.params.path || req.params.path === "/") {
      const to = self(req)
      return redirect(req, res, "login", {
        to: to !== "/" ? to : undefined,
      })
    }
    throw new HttpError("Unauthorized", HttpCode.Unauthorized)
  }

  // The base is used for rewriting (redirects, target).
  if (!opts?.passthroughPath) {
    ;(req as any).base = req.path.split(path.sep).slice(0, 3).join(path.sep)
  }

  _proxy.web(req, res, {
    ignorePath: true,
    target: getProxyTarget(req, opts),
  })
}

export async function wsProxy(
  req: WebsocketRequest,
  opts?: {
    passthroughPath?: boolean
    proxyBasePath?: string

View on GitHub (pinned to 51f90a376b)

Solutions

  1. Authenticate first: log in via /login to obtain a valid session cookie, then retry the proxied request.
  2. For CORS preflight requests that must pass without auth, start code-server with --auth none or set the skip-auth-preflight arg (only if you understand the security implications).
  3. Ensure the reverse proxy forwards the Cookie header and Host/origin so authenticated() validates correctly.
  4. Confirm the cookie name matches req.cookieSessionName and that the cookie domain/path is correct.

Example fix

// client: log in first, then call the proxied port
await loginAndGetCookie()
await fetch('/proxy/3000/api/items', { headers: { Cookie: sessionCookie } })
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling the proxy, ensure the session cookie is present.
function hasSessionCookie(name: string): boolean {
  return document.cookie.split('; ').some(c => c.startsWith(name + '='))
}
if (!hasSessionCookie(cookieSessionName)) await redirectToLogin()

Type guard

// Server-side helper (mirrors authenticated(req))
async function isAuthenticated(req: Request): Promise<boolean> {
  return authenticated(req)
}

Try / catch

// Client: expect a 401 and re-authenticate.
try {
  const res = await fetch(`/proxy/${port}${path}`, { headers: { Cookie } })
  if (res.status === 401) { await login(); return retry() }
} catch (e) { /* network error */ }

Prevention

When it happens

Trigger: A request to /:port/<some-path> where the caller has no valid session cookie, the cookie expired, or skip-auth-preflight is not set so even OPTIONS preflight requests are subject to auth. Also when authenticated(req) returns false due to a missing/invalid password cookie.

Common situations: Session cookie expired; user opened a proxied resource link directly without being logged in; a third-party tool hitting the proxy endpoint without sending credentials; CSRF/auth middleware rejecting the cookie; reverse proxy stripping cookies.

Understand the failure class

Related errors


AI-assisted analysis of coder/code-server@51f90a376b (2026-08-12). Data as JSON: /api/errors/72c21f28025092f4. Report an issue: GitHub.