coder/code-server · error · HttpError

Forbidden

Error message

Forbidden

What it means

ensureProxyEnabled (http.ts:83) is Express middleware guarding the /proxy subdomain proxy routes. If req.args['disable-proxy'] is truthy (set via --disable-proxy), it throws an HttpError with status 403 Forbidden. This prevents access to the proxy feature when an operator has explicitly turned it off.

Source

Thrown at src/node/http.ts:83

): string => {
  const serverOptions: ClientConfiguration = {
    ...createClientConfiguration(req),
    ...extraOpts,
  }

  return content
    .replace(/{{TO}}/g, (typeof req.query.to === "string" && escapeHtml(req.query.to)) || "/")
    .replace(/{{BASE}}/g, serverOptions.base)
    .replace(/{{CS_STATIC_BASE}}/g, serverOptions.csStaticBase)
    .replace("{{OPTIONS}}", () => escapeJSON(serverOptions))
}

/**
 * Throw an error if proxy is not enabled. Call `next` if provided.
 */
export const ensureProxyEnabled = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => {
  if (!proxyEnabled(req)) {
    throw new HttpError("Forbidden", HttpCode.Forbidden)
  }
  if (next) {
    next()
  }
}

/**
 * Return true if proxy is enabled.
 */
export const proxyEnabled = (req: express.Request): boolean => {
  return !req.args["disable-proxy"]
}

/**
 * Throw an error if not authorized. Call `next` if provided.
 */
export const ensureAuthenticated = async (
  req: express.Request,

View on GitHub (pinned to 51f90a376b)

Solutions

  1. Restart code-server without --disable-proxy if the proxy is needed
  2. Update the client/extension to use direct ports instead of the code-server proxy
  3. If 403 is expected, surface a clearer message to the end user (the proxy is intentionally off)

Example fix

# before
code-server --disable-proxy
# client hits https://host/proxy/3000/...

# after
code-server
# proxy routes are enabled
Defensive patterns

Strategy: type-guard

Validate before calling

// Before depending on the proxy, check the runtime args
function proxyIsEnabled(args: { "disable-proxy"?: boolean }): boolean {
  return !args["disable-proxy"]
}
if (!proxyIsEnabled(args)) {
  throw new Error("Proxy is disabled; cannot route to /proxy/")
}

Type guard

import { HttpError, HttpCode } from "../../common/http"
function isForbiddenProxyError(e: unknown): boolean {
  return e instanceof HttpError && e.status === HttpCode.Forbidden && e.message === "Forbidden"
}

Try / catch

try {
  await ensureProxyEnabled(req, res, next)
} catch (e) {
  if (e instanceof HttpError && e.status === HttpCode.Forbidden) {
    res.status(403).send("Proxy is disabled on this server")
  } else throw e
}

Prevention

When it happens

Trigger: An HTTP request to a /proxy/<port>/... path (or subdomain proxy) while code-server was started with `--disable-proxy`, or any route wired through ensureProxyEnabled when the proxy is disabled.

Common situations: Hardening a deployment with --disable-proxy and then a user/app still hitting proxy URLs; leftover bookmarks or extensions that route through the proxy.

Understand the failure class

Related errors


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