louislam/uptime-kuma · warning · Error
The token is invalid due to password change or old token
Error message
The token is invalid due to password change or old token
What it means
Thrown by the 'loginByToken' socket handler after the JWT is successfully decoded and the user is found and active. The token carries an 'h' claim (shake256 of the user's password hash); if it no longer matches the current stored password hash, the token is considered stale. The handler's catch block converts ANY thrown error into the generic i18n callback {ok:false, msg:'authInvalidToken', msgi18n:true}.
Source
Thrown at server/server.js:416
// Public Socket API
// ***************************
socket.on("loginByToken", async (token, callback) => {
const clientIP = await server.getClientIP(socket);
log.info("auth", `Login by token. IP=${clientIP}`);
try {
let decoded = jwt.verify(token, server.jwtSecret);
log.info("auth", "Username from JWT: " + decoded.username);
let user = await R.findOne("user", " username = ? AND active = 1 ", [decoded.username]);
if (user) {
// Check if the password changed
if (decoded.h !== shake256(user.password, SHAKE256_LENGTH)) {
throw new Error("The token is invalid due to password change or old token");
}
log.debug("auth", "afterLogin");
await afterLogin(socket, user);
log.debug("auth", "afterLogin ok");
log.info("auth", `Successfully logged in user ${decoded.username}. IP=${clientIP}`);
callback({
ok: true,
});
} else {
log.info("auth", `Inactive or deleted user ${decoded.username}. IP=${clientIP}`);
callback({
ok: false,
msg: "authUserInactiveOrDeleted",
msgi18n: true,View on GitHub (pinned to 6b5ea01557)
Solutions
- On receiving authInvalidToken / ok:false, clear the stored token and redirect the user to the login screen.
- After a password change, have all clients discard their cached JWT (the server already disconnects other sockets).
- Do not reuse tokens across instances with different jwtSecret or restored DBs.
- Ensure the client does not pin a token forever; re-authenticate on this error.
Example fix
// before
socket.emit('loginByToken', token, (res) => { if (!res.ok) console.warn(res.msg); });
// after
socket.emit('loginByToken', token, (res) => {
if (!res.ok) { localStorage.removeItem('token'); router.push('/login'); }
}); Defensive patterns
Strategy: fallback
Validate before calling
// Before relying on a stored token, be ready to re-authenticate on failure
function isTokenLikelyStale(token, knownHashFingerprint) {
try { const d = jwt.decode(token); return !d || d.h !== knownHashFingerprint; }
catch { return true; }
} Type guard
function isStaleTokenResponse(res) {
return res && res.ok === false && res.msg === 'authInvalidToken';
} Try / catch
socket.emit('loginByToken', token, (res) => {
if (!res.ok) {
// token invalid: password changed, old token, or user inactive
localStorage.removeItem('token');
return router.push('/login');
}
}); Prevention
- On authInvalidToken, always clear the stored token and re-login.
- After a password change, force all clients to drop cached tokens.
- Do not persist tokens across DB restores or jwtSecret rotations.
- Treat this as an expected auth flow, not a bug.
When it happens
Trigger: The client presents a JWT saved before the user's password was changed/reset; the password hash in the DB changed; or an old token from a previous secret rotation is replayed. The client ultimately receives 'authInvalidToken'.
Common situations: User changed their password on another device; admin reset the password; the DB was restored from a backup with different hashes; token persisted in localStorage across a password change; jwtSecret changed (though that usually fails jwt.verify first).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- You are not logged in.
- Invalid new password
- Incorrect current password
- The oauth config is invalid. ${e.message}
- The oauth config is invalid. ${e.message}
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/d824c3ba09b59894.
Report an issue: GitHub.