Wei-Shaw/sub2api · error

concurrency must be >= 0

Error message

concurrency must be >= 0

What it means

Returned by validateDataAccount (backend/internal/handler/admin/account_data.go:700) when an accounts[] entry sets concurrency to a negative integer. Concurrency is a plain int (0 passes and means the default/no override), so any value below 0 — including -1 sentinels meaning 'unlimited' — is rejected. The priority field has the same non-negative rule checked next.

Source

Thrown at backend/internal/handler/admin/account_data.go:700

	if strings.TrimSpace(item.Platform) == "" {
		return errors.New("account platform is required")
	}
	if strings.TrimSpace(item.Type) == "" {
		return errors.New("account type is required")
	}
	if len(item.Credentials) == 0 {
		return errors.New("account credentials is required")
	}
	switch item.Type {
	case service.AccountTypeOAuth, service.AccountTypeSetupToken, service.AccountTypeAPIKey, service.AccountTypeUpstream:
	default:
		return fmt.Errorf("account type is invalid: %s", item.Type)
	}
	if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
		return errors.New("rate_multiplier must be >= 0")
	}
	if item.Concurrency < 0 {
		return errors.New("concurrency must be >= 0")
	}
	if item.Priority < 0 {
		return errors.New("priority must be >= 0")
	}
	return nil
}

func defaultProxyName(name string) string {
	if strings.TrimSpace(name) == "" {
		return "imported-proxy"
	}
	return name
}

// enrichCredentialsFromIDToken performs best-effort extraction of user info fields
// (email, plan_type, chatgpt_account_id, etc.) from id_token in credentials.
// Only applies to OpenAI OAuth accounts. Skips expired token errors silently.
// Existing credential values are never overwritten — only missing fields are filled.

View on GitHub (pinned to 073e92d171)

Solutions

  1. Set concurrency to 0 (use default) or a positive integer; remove the field to omit it.
  2. Map 'unlimited' from source systems to the platform's supported max or just omit the field.
  3. Add min=0 constraint in the form/spreadsheet that produces the value.

Example fix

// before
{ "name": "main", "platform": "openai", "type": "oauth", "credentials": { ... }, "concurrency": -1 }

// after
{ "name": "main", "platform": "openai", "type": "oauth", "credentials": { ... }, "concurrency": 0 }
Defensive patterns

Strategy: validation

Validate before calling

function hasValidConcurrency(entry: Record<string, unknown>): boolean {
  const c = entry.concurrency
  return c === undefined || c === null || (typeof c === 'number' && Number.isInteger(c) && c >= 0)
}

Type guard

function isOptionalNonNegativeInt(n: unknown): n is number | undefined {
  return n === undefined || n === null || (typeof n === 'number' && Number.isInteger(n) && n >= 0)
}

Prevention

When it happens

Trigger: An account entry with "concurrency": -1 or lower; computed concurrency from capacity math that underflowed; conventions where -1 means unlimited colliding with this schema.

Common situations: Importing from a system that uses -1 for unlimited; spreadsheet or UI inputs allowing negatives; decimal values like 0.5 truncated oddly.

Related errors


AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15). Data as JSON: /api/errors/9f4bb207ebb9eed8. Report an issue: GitHub.