louislam/dockge · 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
During JWT-based auto-login (the 'loginByToken' socket event), the decoded token carries an 'h' field: a shake256 hash of the user's password hash at token-issue time. If the stored password hash no longer matches (the password was changed or the token is stale from a previous incarnation), the handler throws this Error so the client is forced to re-authenticate with credentials.
Source
Thrown at backend/socket-handlers/main-socket-handler.ts:83
// Login by token
socket.on("loginByToken", async (token, callback) => {
const clientIP = await server.getClientIP(socket);
log.info("auth", `Login by token. IP=${clientIP}`);
try {
const decoded = jwt.verify(token, server.jwtSecret) as JWTDecoded;
log.info("auth", "Username from JWT: " + decoded.username);
const user = await R.findOne("user", " username = ? AND active = 1 ", [
decoded.username,
]) as User;
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 server.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",View on GitHub (pinned to f809ae192b)
Solutions
- Discard the stored token and log in again with username/password to obtain a fresh JWT.
- If the password was intentionally changed, no repair is needed — the old token is invalid by design.
- Clear client-side token storage (localStorage/cookie) when handling this error.
Example fix
// before
socket.emit('loginByToken', savedToken, cb); // may throw
// after
socket.emit('loginByToken', savedToken, (res) => {
if (!res.ok) localStorage.removeItem('token');
}); Defensive patterns
Strategy: fallback
Validate before calling
// Detect stale token by decoding expiry locally before use
function tokenLooksValid(token) {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
return payload.exp * 1000 > Date.now();
} catch { return false; }
} Try / catch
socket.emit('loginByToken', token, (res) => {
if (!res.ok && /invalid/.test(res.msg || '')) {
localStorage.removeItem('token');
showLoginForm();
}
}); Prevention
- Clear stored tokens after any password change
- Re-authenticate with credentials when token login fails
- Avoid reusing tokens across environments or restored databases
When it happens
Trigger: Emitting 'loginByToken' with a JWT minted before a password change, or a token persisted from an earlier Dockge install/database where the user's password hash differed.
Common situations: Browser keeps a saved token while the admin rotates the password; restoring an old database while clients retain old tokens; token copied from another environment with different password hashes.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Password is too weak. It should contain alphabetic and numer
- Dockge has been initialized. If you want to run setup again,
- Invalid new password
- You are not logged in.
- Wrong data type?
AI-assisted analysis of louislam/dockge@f809ae192b (2026-08-31).
Data as JSON: /api/errors/411991175265039e.
Report an issue: GitHub.