usememos/memos · warning

PAT not found

Error message

PAT not found

What it means

The PostgreSQL user_setting driver performs the same PAT lookup as the MySQL one but scans rows in SQL; after exhausting rows without a TokenHash match (and with rows.Err() clean) it returns "PAT not found". Semantics are identical: the hash is absent from the user's stored PAT list.

Source

Thrown at store/db/postgres/user_setting.go:136

			continue // Skip invalid JSON
		}

		// Search for matching token hash
		for _, pat := range patsUserSetting.Tokens {
			if pat.TokenHash == tokenHash {
				return &store.PATQueryResult{
					UserID: userID,
					PAT:    pat,
				}, nil
			}
		}
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return nil, errors.New("PAT not found")
}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Issue a fresh PAT and update downstream secrets/scripts
  2. Ensure the hash function used for lookup matches the one used at token creation
  3. Translate this store error into an unauthenticated response in the auth middleware

Example fix

# before (client)
curl -H "Authorization: Bearer $OLD_REVOKED_PAT" ...
# after
# create a new PAT in the web UI, then
curl -H "Authorization: Bearer $NEW_PAT" ...
Defensive patterns

Strategy: try-catch

Try / catch

res, err := d.FindPAT(ctx, userID, tokenHash)
if err != nil {
    if strings.Contains(err.Error(), "PAT not found") {
        return nil, status.Error(codes.Unauthenticated, "invalid personal access token")
    }
    return nil, err
}

Prevention

When it happens

Trigger: Presenting a PAT whose SHA hash is not stored for the queried user; revoked tokens; hash computed with a different scheme than at creation time.

Common situations: Scripts holding stale PATs after instance reinstall (DB wiped); tokens from another environment (staging vs prod); user account recreated with the same ID.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/e346185a6921b709. Report an issue: GitHub.