{"record":{"id":"83da4b33adf0f4b5","repo":"coder/code-server","slug":"missing-password","errorCode":null,"errorMessage":"Missing password","messagePattern":"Missing password","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/node/routes/login.ts","lineNumber":82,"sourceCode":"  next()\n})\n\nrouter.get(\"/\", async (req, res) => {\n  res.send(await getRoot(req))\n})\n\nrouter.post<{}, string, { password?: string; base?: string } | undefined, { to?: string }>(\"/\", async (req, res) => {\n  const password = sanitizeString(req.body?.password)\n  const hashedPasswordFromArgs = req.args[\"hashed-password\"]\n\n  try {\n    // Check to see if they exceeded their login attempts\n    if (!limiter.canTry()) {\n      throw new Error(i18n.t(\"LOGIN_RATE_LIMIT\") as string)\n    }\n\n    if (!password) {\n      throw new Error(i18n.t(\"MISS_PASSWORD\") as string)\n    }\n\n    const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)\n    const { isPasswordValid, hashedPassword } = await handlePasswordValidation({\n      passwordMethod,\n      hashedPasswordFromArgs,\n      passwordFromRequestBody: password,\n      passwordFromArgs: req.args.password,\n    })\n\n    if (isPasswordValid) {\n      // The hash does not add any actual security but we do it for\n      // obfuscation purposes (and as a side effect it handles escaping).\n      res.cookie(req.cookieSessionName, hashedPassword, getCookieOptions(req))\n\n      const to = (typeof req.query.to === \"string\" && req.query.to) || \"/\"\n      return redirect(req, res, to, { to: undefined })\n    }","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/src/node/routes/login.ts#L64-L100","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Verify the field name is exactly 'password' (sanitizeString is applied to req.body.password).","If behind a reverse proxy, confirm it forwards the request body and Content-Type unchanged.","In a custom client, validate the field is non-empty before posting to avoid the re-rendered error page."],"exampleFix":"// before\nawait fetch('/login', { method: 'POST', body: JSON.stringify({}) })\n// after\nawait fetch('/login', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ password: userPassword }),\n})","handlingStrategy":"validation","validationCode":"// Client-side: validate before posting to /login\nfunction buildLoginBody(form) {\n  const password = (form.password?.value ?? '').trim()\n  if (!password) throw new Error('Password is required')\n  return JSON.stringify({ password })\n}\n// Server-side mirror:\nconst password = sanitizeString(req.body?.password)\nif (!password) return res.status(400).send('password required')","typeGuard":"function hasPassword(body: unknown): body is { password: string } {\n  return typeof body === 'object' && body !== null\n    && typeof (body as any).password === 'string'\n    && (body as any).password.trim().length > 0\n}","tryCatchPattern":"// The handler already wraps everything in try/catch and re-renders login.html.\n// In a custom client, detect the re-rendered HTML (no JSON) as a login failure:\ntry {\n  const res = await fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body, redirect: 'manual' })\n  if (res.status >= 400 || res.headers.get('content-type')?.includes('text/html')) {\n    throw new Error('Login failed (possibly missing password)')\n  }\n} catch (e) { /* surface to UI */ }","preventionTips":["Always validate the password field is non-empty on the client before posting.","Send Content-Type: application/json so Express parses the body.","Use the exact field name 'password'.","Treat a 200 with text/html (not a redirect) as a login-form error in programmatic clients."],"tags":["authentication","login","i18n","validation"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}