vxcontrol/pentagi · error
token not found in database
Error message
token not found in database
What it means
The bearer token's JWT is valid, but its TokenID has no matching row in the API tokens table (gorm.ErrRecordNotFound from tokenCache.GetStatus), so the middleware fails authentication. This means the token was deleted after issuance, belongs to a wiped/recreated database, or never existed in this installation.
Source
Thrown at backend/pkg/server/auth/auth_middleware.go:225
return authResultSkip, errors.New("token can't be empty")
}
// skip validation if using default salt (for backward compatibility)
if p.globalSalt == "" || p.globalSalt == "salt" {
return authResultSkip, errors.New("token validation disabled with default salt")
}
// try to validate as API token first (new format with JWT signing key)
apiClaims, apiErr := ValidateAPIToken(token, p.globalSalt)
if apiErr != nil {
return authResultFail, errors.New("token is invalid")
}
// check token status and get privileges through cache
status, privileges, err := p.tokenCache.GetStatus(apiClaims.TokenID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return authResultFail, errors.New("token not found in database")
}
return authResultFail, fmt.Errorf("error checking token status: %w", err)
}
if status != models.TokenStatusActive {
return authResultFail, errors.New("token has been revoked")
}
// Verify user hash matches database
dbHash, userStatus, err := p.userCache.GetUserHash(apiClaims.UID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return authResultFail, errors.New("user has been deleted")
}
return authResultFail, fmt.Errorf("error checking user status: %w", err)
}
if userStatus == models.UserStatusBlocked {
return authResultFail, errors.New("user has been blocked")View on GitHub (pinned to ea665308ba)
Solutions
- Create a new API token in the current environment's settings UI and replace the client's credential.
- Verify the client is pointed at the intended environment (check the API base URL).
- If a backup restore removed tokens, reissue them for all automation users.
- Audit for scripts still holding old tokens after cleanup and rotate them.
Example fix
// before const API = "https://prod.example.com"; const token = stagingToken; // after const API = "https://prod.example.com"; const token = prodToken; // minted in the same environment as API
Defensive patterns
Strategy: fallback
Validate before calling
# verify the token exists before shipping it to a client: # SELECT 1 FROM api_tokens WHERE token_id = '<id>' AND status = 'active';
Try / catch
try {
return await call(token);
} catch (e) {
if (is401(e) && /not found in database/i.test(e.message)) {
logger.error("Token unknown to this environment — mint a new one here");
return await call(await mintNewToken());
}
throw e;
} Prevention
- Keep a 1:1 mapping between tokens and the environment they were minted in.
- Re-mint tokens after any DB restore or environment rebuild.
- Track token IDs in a secret manager with environment labels.
When it happens
Trigger: Calling with an API token whose record was deleted from the tokens table; pointing a client at a different environment (staging token against production DB); restoring the database from a backup that predates the token.
Common situations: Token revoked by deletion rather than status change; environment misconfiguration (wrong DATABASE_URL); CI using a token from a teammate's local instance; DB migration dropping the tokens table data.
Related errors
- token is invalid
- token has been revoked
- error checking token status: %w
- token required
- bearer scheme must be used
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/7e5046a0086b6f39.
Report an issue: GitHub.