coder/code-server · warning · Error

Missing password

Error message

Missing password

What it means

Thrown by the code-server POST /login handler when the submitted request body contains no password after sanitizeString() normalization. The message is resolved through i18n.t('MISS_PASSWORD'), so its exact text depends on the configured locale. It is caught in the same handler's catch block and re-rendered into the login.html page as an inline error div, so the user sees it inside the login form rather than as a JSON error.

Source

Thrown at src/node/routes/login.ts:82

  next()
})

router.get("/", async (req, res) => {
  res.send(await getRoot(req))
})

router.post<{}, string, { password?: string; base?: string } | undefined, { to?: string }>("/", async (req, res) => {
  const password = sanitizeString(req.body?.password)
  const hashedPasswordFromArgs = req.args["hashed-password"]

  try {
    // Check to see if they exceeded their login attempts
    if (!limiter.canTry()) {
      throw new Error(i18n.t("LOGIN_RATE_LIMIT") as string)
    }

    if (!password) {
      throw new Error(i18n.t("MISS_PASSWORD") as string)
    }

    const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
    const { isPasswordValid, hashedPassword } = await handlePasswordValidation({
      passwordMethod,
      hashedPasswordFromArgs,
      passwordFromRequestBody: password,
      passwordFromArgs: req.args.password,
    })

    if (isPasswordValid) {
      // The hash does not add any actual security but we do it for
      // obfuscation purposes (and as a side effect it handles escaping).
      res.cookie(req.cookieSessionName, hashedPassword, getCookieOptions(req))

      const to = (typeof req.query.to === "string" && req.query.to) || "/"
      return redirect(req, res, to, { to: undefined })
    }

View on GitHub (pinned to 51f90a376b)

Solutions

  1. Ensure the login POST includes a non-empty password field: send JSON { "password": "<value>" } with header Content-Type: application/json, or submit the HTML form with the password input filled.
  2. Verify the field name is exactly 'password' (sanitizeString is applied to req.body.password).
  3. If behind a reverse proxy, confirm it forwards the request body and Content-Type unchanged.
  4. In a custom client, validate the field is non-empty before posting to avoid the re-rendered error page.

Example fix

// before
await fetch('/login', { method: 'POST', body: JSON.stringify({}) })
// after
await fetch('/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ password: userPassword }),
})
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: validate before posting to /login
function buildLoginBody(form) {
  const password = (form.password?.value ?? '').trim()
  if (!password) throw new Error('Password is required')
  return JSON.stringify({ password })
}
// Server-side mirror:
const password = sanitizeString(req.body?.password)
if (!password) return res.status(400).send('password required')

Type guard

function hasPassword(body: unknown): body is { password: string } {
  return typeof body === 'object' && body !== null
    && typeof (body as any).password === 'string'
    && (body as any).password.trim().length > 0
}

Try / catch

// The handler already wraps everything in try/catch and re-renders login.html.
// In a custom client, detect the re-rendered HTML (no JSON) as a login failure:
try {
  const res = await fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body, redirect: 'manual' })
  if (res.status >= 400 || res.headers.get('content-type')?.includes('text/html')) {
    throw new Error('Login failed (possibly missing password)')
  }
} catch (e) { /* surface to UI */ }

Prevention

When it happens

Trigger: A POST to the login route (router.post('/', ...)) where req.body.password is undefined, empty, or sanitizes to an empty string (sanitizeString strips/trims input). This happens when the login form is submitted with a blank password field, when a programmatic client posts a body without the password key, or when Content-Type is not JSON/form so Express fails to parse req.body.

Common situations: Automated login scripts that omit the password field; a frontend form submission bug that sends an empty value; misconfigured reverse proxy that strips the POST body; Content-Type header missing so body-parser leaves req.body undefined; a custom UI that posts to /login with the wrong field name.

Related errors


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