Wei-Shaw/sub2api · error

account platform is required

Error message

account platform is required

What it means

Returned by validateDataAccount (backend/internal/handler/admin/account_data.go:683) when an accounts[] entry has a non-empty name but its platform is empty after TrimSpace. Platform identifies which upstream the account belongs to and is required on every imported account.

Solutions

  1. Set platform to the expected platform identifier (e.g. "openai") on the entry.
  2. Check the export/import schema docs for the exact field name and allowed values.
  3. Map renamed fields when converting from other formats.

Example fix

// before
{ "name": "main", "type": "oauth", "credentials": { ... } }

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

Strategy: validation

Validate before calling

function hasAccountPlatform(entry: Record<string, unknown>): boolean {
  return typeof entry.platform === 'string' && entry.platform.trim() !== ''
}

Type guard

function hasRequiredAccountStrings(e: unknown, keys: string[]): e is Record<string, string> {
  if (typeof e !== 'object' || e === null) return false
  const o = e as Record<string, unknown>
  return keys.every((k) => typeof o[k] === 'string' && (o[k] as string).trim() !== '')
}

Prevention

When it happens

Trigger: An account object with name and type but platform missing/blank; a key renamed (e.g. 'provider') so platform is never set.

Common situations: Schema drift between export tools; hand-written payloads guessing field names; whitespace platform values from forms.

Related errors


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

Appendix: source

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

	case "http", "https", "socks5", "socks5h":
	default:
		return fmt.Errorf("proxy protocol is invalid: %s", item.Protocol)
	}
	if item.Status != "" {
		normalizedStatus := normalizeProxyStatus(item.Status)
		if normalizedStatus != service.StatusActive && normalizedStatus != "inactive" {
			return fmt.Errorf("proxy status is invalid: %s", item.Status)
		}
	}
	return nil
}

func validateDataAccount(item DataAccount) error {
	if strings.TrimSpace(item.Name) == "" {
		return errors.New("account name is required")
	}
	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")
	}

View on GitHub (pinned to 073e92d171)