{"record":{"id":"a9abbf3c3fb48e77","repo":"vxcontrol/pentagi","slug":"invalid-tokenstatus-s","errorCode":null,"errorMessage":"invalid TokenStatus: %s","messagePattern":"invalid TokenStatus: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/server/models/api_tokens.go","lineNumber":30,"sourceCode":"type TokenStatus string\n\nconst (\n\tTokenStatusActive  TokenStatus = \"active\"\n\tTokenStatusRevoked TokenStatus = \"revoked\"\n\tTokenStatusExpired TokenStatus = \"expired\"\n)\n\nfunc (s TokenStatus) String() string {\n\treturn string(s)\n}\n\n// Valid is function to control input/output data\nfunc (s TokenStatus) Valid() error {\n\tswitch s {\n\tcase TokenStatusActive, TokenStatusRevoked, TokenStatusExpired:\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid TokenStatus: %s\", s)\n\t}\n}\n\n// Validate is function to use callback to control input/output data\nfunc (s TokenStatus) Validate(db *gorm.DB) {\n\tif err := s.Valid(); err != nil {\n\t\tdb.AddError(err)\n\t}\n}\n\n// APIToken is model to contain API token metadata\n// nolint:lll\ntype APIToken struct {\n\tID        uint64      `form:\"id\" json:\"id\" validate:\"min=0,numeric\" gorm:\"type:BIGINT;NOT NULL;PRIMARY_KEY;AUTO_INCREMENT\"`\n\tTokenID   string      `form:\"token_id\" json:\"token_id\" validate:\"required,len=10\" gorm:\"type:TEXT;NOT NULL;UNIQUE_INDEX\"`\n\tUserID    uint64      `form:\"user_id\" json:\"user_id\" validate:\"min=0,numeric\" gorm:\"type:BIGINT;NOT NULL\"`\n\tRoleID    uint64      `form:\"role_id\" json:\"role_id\" validate:\"min=0,numeric\" gorm:\"type:BIGINT;NOT NULL\"`\n\tName      *string     `form:\"name,omitempty\" json:\"name,omitempty\" validate:\"omitempty,max=100\" gorm:\"type:TEXT\"`","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/models/api_tokens.go#L12-L48","documentation":"TokenStatus.Valid() in backend/pkg/server/models/api_tokens.go accepts only TokenStatusActive, TokenStatusRevoked, and TokenStatusExpired; any other string fails via the GORM Validate callback. It guards the lifecycle state of API tokens so no arbitrary status can be written or queried.","triggerScenarios":"Creating/updating an API token with a status like \"disabled\", \"deleted\", \"inactive\", or empty; filtering the token list by an unknown status value.","commonSituations":"Client assumes additional token states exist (e.g. \"disabled\"); case mismatch such as \"Active\" vs \"active\"; stale client SDK from before a status rename; manual DB/API edits introducing an out-of-whitelist value.","solutions":["Use one of the valid statuses exactly: active, revoked, or expired (per the TokenStatus constants).","If you mean to disable a token, use \"revoked\" — that is the library's term for a disabled token.","Fix casing/whitespace in the submitted value; the comparison is exact string equality.","Regenerate client types from the current schema if your SDK predates the status list."],"exampleFix":"// before\n{\"status\": \"disabled\"}\n// after\n{\"status\": \"revoked\"}","handlingStrategy":"validation","validationCode":"const TOKEN_STATUSES = [\"active\", \"revoked\", \"expired\"] as const;\nfunction isValidTokenStatus(s: string): boolean {\n  return (TOKEN_STATUSES as readonly string[]).includes(s);\n}\nif (!isValidTokenStatus(input.status)) throw new Error(`invalid TokenStatus: ${input.status}`);","typeGuard":"function isTokenStatus(v: unknown): v is \"active\" | \"revoked\" | \"expired\" {\n  return v === \"active\" || v === \"revoked\" || v === \"expired\";\n}","tryCatchPattern":"try {\n  await api.updateToken(id, { status });\n} catch (err) {\n  if (String(err).includes(\"invalid TokenStatus\")) {\n    // map synonyms: disabled/inactive -> revoked, then retry once\n    await api.updateToken(id, { status: \"revoked\" });\n  } else throw err;\n}","preventionTips":["Treat \"revoked\" as the only way to disable a token; never send \"disabled\"/\"inactive\".","Regenerate GraphQL/TS types after schema changes so the enum stays in sync.","Normalize user input to lowercase before sending.","Keep a single shared constant list mirrored from api_tokens.go instead of string literals."],"tags":["validation","enum","api-tokens","gorm"],"backgroundTag":"invalid-enum-value","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}