{"record":{"id":"a0a06deabd43227d","repo":"coder/code-server","slug":"incorrect-password","errorCode":null,"errorMessage":"Incorrect password","messagePattern":"Incorrect password","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/node/routes/login.ts","lineNumber":116,"sourceCode":"      const to = (typeof req.query.to === \"string\" && req.query.to) || \"/\"\n      return redirect(req, res, to, { to: undefined })\n    }\n\n    // Note: successful logins should not count against the RateLimiter\n    // which is why this logic must come after the successful login logic\n    limiter.removeToken()\n\n    console.error(\n      \"Failed login attempt\",\n      JSON.stringify({\n        xForwardedFor: req.headers[\"x-forwarded-for\"],\n        remoteAddress: req.connection.remoteAddress,\n        userAgent: req.headers[\"user-agent\"],\n        timestamp: Math.floor(new Date().getTime() / 1000),\n      }),\n    )\n\n    throw new Error(i18n.t(\"INCORRECT_PASSWORD\") as string)\n  } catch (error: any) {\n    const renderedHtml = await getRoot(req, error)\n    res.send(renderedHtml)\n  }\n})\n","sourceCodeStart":98,"sourceCodeEnd":122,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/src/node/routes/login.ts#L98-L122","documentation":"Thrown by the POST /login handler after a password is supplied but fails validation in handlePasswordValidation(). Before throwing, the handler calls limiter.removeToken() to consume a rate-limit token and logs a structured 'Failed login attempt' record. Like the missing-password error it is caught locally and rendered back into login.html as an inline error, so the caller receives a 200 with HTML, not a 401.","triggerScenarios":"POST /login with a non-empty password that does not match the configured password method: a wrong plaintext/argon2/sha256 hash comparison, an expired PASSWORD env var, or a hashed-password arg whose hash the supplied password does not satisfy. Each wrong attempt also drains the RateLimiter (2/min, 12/hour).","commonSituations":"User mistypes the password; the server was restarted with a different PASSWORD or --hashed-password value; the client cached an old password; copy-paste of a hash with a missing or extra character; switching password methods (plain -> argon2) without updating clients.","solutions":["Confirm the correct password for the currently configured auth: check PASSWORD / --hashed-password on the running code-server process.","If using --hashed-password, regenerate the hash and confirm its method (argon2i/d, sha256) matches what handlePasswordValidation expects.","Wait for the rate limiter window to reset if repeated wrong attempts triggered LOGIN_RATE_LIMIT (the limiter blocks further tries).","Check server logs for the 'Failed login attempt' JSON entries to see source IP/UA of failing attempts."],"exampleFix":"// regenerate an argon2 hashed password\necho -n 'mypassword' | argon2 somesalt -id -l 32 -p 2 -t 3 -e\n# then start with: code-server --hashed-password '$argon2id$...'","handlingStrategy":"validation","validationCode":"// Before login, sanity-check the password against the expected method locally where possible.\n// For argon2 hashed passwords you can verify with the argon2 module:\nimport argon2 from 'argon2'\nconst ok = await argon2.verify(storedHash, candidate)\nif (!ok) throw new Error('Password does not match the configured hash')","typeGuard":"// Ensure the configured hashed password is a known method before relying on it.\nfunction isKnownHashMethod(h: string): boolean {\n  return h.startsWith('$argon2') || /^[a-f0-9]{64}$/i.test(h) // argon2 or sha256\n}","tryCatchPattern":"// The route's try/catch already catches INCORRECT_PASSWORD and renders it inline.\n// In a programmatic client, handle the re-rendered HTML / cookie absence:\ntry {\n  await postLogin(password)\n  if (!document.cookie.includes(cookieName)) throw new Error('login failed')\n} catch (e) { /* show error, do NOT retry in a tight loop (rate limiter!) */ }","preventionTips":["Do not retry wrong passwords in a loop — the RateLimiter (2/min, 12/hour) will lock you out.","Keep the configured PASSWORD / --hashed-password in sync across restarts.","Verify the hash method matches what handlePasswordValidation expects.","Log failed-attempt JSON server-side to audit brute-force attempts."],"tags":["authentication","login","password","rate-limit"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}