{"record":{"id":"eba9b5771f86c949","repo":"multica-ai/multica","slug":"cloud-pat-invalid","errorCode":null,"errorMessage":"cloud pat invalid","messagePattern":"cloud pat invalid","errorType":"http","errorClass":"ErrCloudPATInvalid","httpStatus":401,"severity":"error","filePath":"server/internal/auth/cloud_pat.go","lineNumber":82,"sourceCode":"\n// cloudPATDefaultTimeout is the per-request HTTP timeout for verify\n// calls when the caller doesn't supply an *http.Client. Auth must\n// stay snappy: Fleet should answer in tens of milliseconds, and a\n// hung verify would block every incoming request behind it. Tighter\n// than cloudruntime's 35s because that one proxies arbitrary user\n// traffic; this one only ever sees a small JSON exchange.\nconst cloudPATDefaultTimeout = 5 * time.Second\n\n// Verifier sentinel errors. Callers (the Auth / DaemonAuth middlewares)\n// branch on these to map cloud outcomes onto HTTP status codes:\n//\n//   - ErrCloudPATInvalid       → 401 (Fleet says token is bad)\n//   - ErrCloudPATUnavailable   → 503 (Fleet unreachable / 5xx)\n//   - ErrCloudPATNotConfigured → 401 (server has no Fleet URL set; we\n//     don't reveal that mcn_ is \"supported but disabled\" — failing\n//     closed avoids treating misconfigured prod the same as enabled)\nvar (\n\tErrCloudPATInvalid       = errors.New(\"cloud pat invalid\")\n\tErrCloudPATUnavailable   = errors.New(\"cloud pat verifier unavailable\")\n\tErrCloudPATNotConfigured = errors.New(\"cloud pat verifier not configured\")\n)\n\n// CloudPATIdentity is what a successful verify resolves to. We keep\n// only the fields the auth path actually needs:\n//\n//   - OwnerID is the user whose request this is (mapped to X-User-ID).\n//   - InstanceID / InstanceRecordID are recorded so downstream code can\n//     correlate the request with a specific cloud node; they are not\n//     used for authorization today, but stashing them now keeps the\n//     wire shape stable for callers that later want to assert a\n//     particular instance binding.\n//\n// We deliberately drop token_last4, status, issued_at, etc. — those\n// are diagnostic fields that don't belong in cached auth state.\ntype CloudPATIdentity struct {\n\tOwnerID          string `json:\"o\"`","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/auth/cloud_pat.go#L64-L100","documentation":"Sentinel error ErrCloudPATInvalid in server/internal/auth/cloud_pat.go: the Fleet (cloud) verification endpoint answered definitively that the presented mcn_ personal access token is invalid. Per the doc comment, the Auth/DaemonAuth middlewares map it to HTTP 401. It means the token reached Fleet and was rejected — expired, revoked, or malformed — as opposed to Fleet being unreachable (ErrCloudPATUnavailable, 503).","triggerScenarios":"Request with an mcn_ PAT that Fleet no longer accepts (revoked in the cloud console, expired); token truncated or with stray whitespace/quotes when pasted; token issued for a different Fleet instance than the configured URL.","commonSituations":"User rotated their cloud PAT but the server config or CLI still holds the old one; copy/paste damage when storing the token; environment pointing at a different Fleet environment (staging vs prod) than where the token was created.","solutions":["Generate a new PAT in the cloud console and replace the stored credential, then retry.","Verify the token string was copied whole (no leading/trailing whitespace or shell-quoting artifacts).","Confirm the Fleet URL configured on the server matches the environment the token was issued in.","Distinguish from 503/unavailable: a 401 means Fleet answered, so do not retry the same token."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, auth.ErrCloudPATInvalid) {\n    http.Error(w, \"cloud token rejected; re-authenticate\", http.StatusUnauthorized)\n    return\n}","preventionTips":["Rotate PATs ahead of expiry and update stored credentials everywhere at once.","Store tokens verbatim — never re-type them; use copy/paste or secret managers.","Match the token's Fleet environment with the server's configured Fleet URL."],"tags":["auth","pat","cloud","fleet","http-401","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}