vxcontrol/pentagi · error

invalid TokenStatus

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.

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.

Appendix: 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)