vxcontrol/pentagi · error

invalid TokenStatus: %s

Error message

invalid TokenStatus: %s

What it means

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.

Source

Thrown at backend/pkg/server/models/api_tokens.go:30

type TokenStatus string

const (
	TokenStatusActive  TokenStatus = "active"
	TokenStatusRevoked TokenStatus = "revoked"
	TokenStatusExpired TokenStatus = "expired"
)

func (s TokenStatus) String() string {
	return string(s)
}

// Valid is function to control input/output data
func (s TokenStatus) Valid() error {
	switch s {
	case TokenStatusActive, TokenStatusRevoked, TokenStatusExpired:
		return nil
	default:
		return fmt.Errorf("invalid TokenStatus: %s", s)
	}
}

// Validate is function to use callback to control input/output data
func (s TokenStatus) Validate(db *gorm.DB) {
	if err := s.Valid(); err != nil {
		db.AddError(err)
	}
}

// APIToken is model to contain API token metadata
// nolint:lll
type APIToken struct {
	ID        uint64      `form:"id" json:"id" validate:"min=0,numeric" gorm:"type:BIGINT;NOT NULL;PRIMARY_KEY;AUTO_INCREMENT"`
	TokenID   string      `form:"token_id" json:"token_id" validate:"required,len=10" gorm:"type:TEXT;NOT NULL;UNIQUE_INDEX"`
	UserID    uint64      `form:"user_id" json:"user_id" validate:"min=0,numeric" gorm:"type:BIGINT;NOT NULL"`
	RoleID    uint64      `form:"role_id" json:"role_id" validate:"min=0,numeric" gorm:"type:BIGINT;NOT NULL"`
	Name      *string     `form:"name,omitempty" json:"name,omitempty" validate:"omitempty,max=100" gorm:"type:TEXT"`

View on GitHub (pinned to ea665308ba)

Solutions

  1. Use one of the valid statuses exactly: active, revoked, or expired (per the TokenStatus constants).
  2. If you mean to disable a token, use "revoked" — that is the library's term for a disabled token.
  3. Fix casing/whitespace in the submitted value; the comparison is exact string equality.
  4. Regenerate client types from the current schema if your SDK predates the status list.

Example fix

// before
{"status": "disabled"}
// after
{"status": "revoked"}
Defensive patterns

Strategy: validation

Validate before calling

const TOKEN_STATUSES = ["active", "revoked", "expired"] as const;
function isValidTokenStatus(s: string): boolean {
  return (TOKEN_STATUSES as readonly string[]).includes(s);
}
if (!isValidTokenStatus(input.status)) throw new Error(`invalid TokenStatus: ${input.status}`);

Type guard

function isTokenStatus(v: unknown): v is "active" | "revoked" | "expired" {
  return v === "active" || v === "revoked" || v === "expired";
}

Try / catch

try {
  await api.updateToken(id, { status });
} catch (err) {
  if (String(err).includes("invalid TokenStatus")) {
    // map synonyms: disabled/inactive -> revoked, then retry once
    await api.updateToken(id, { status: "revoked" });
  } else throw err;
}

Prevention

When it happens

Trigger: Creating/updating an API token with a status like "disabled", "deleted", "inactive", or empty; filtering the token list by an unknown status value.

Common situations: 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.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/a9abbf3c3fb48e77. Report an issue: GitHub.