{"record":{"id":"9f4bb207ebb9eed8","repo":"Wei-Shaw/sub2api","slug":"concurrency-must-be-0","errorCode":null,"errorMessage":"concurrency must be >= 0","messagePattern":"concurrency must be >= 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/internal/handler/admin/account_data.go","lineNumber":700,"sourceCode":"\tif strings.TrimSpace(item.Platform) == \"\" {\n\t\treturn errors.New(\"account platform is required\")\n\t}\n\tif strings.TrimSpace(item.Type) == \"\" {\n\t\treturn errors.New(\"account type is required\")\n\t}\n\tif len(item.Credentials) == 0 {\n\t\treturn errors.New(\"account credentials is required\")\n\t}\n\tswitch item.Type {\n\tcase service.AccountTypeOAuth, service.AccountTypeSetupToken, service.AccountTypeAPIKey, service.AccountTypeUpstream:\n\tdefault:\n\t\treturn fmt.Errorf(\"account type is invalid: %s\", item.Type)\n\t}\n\tif item.RateMultiplier != nil && *item.RateMultiplier < 0 {\n\t\treturn errors.New(\"rate_multiplier must be >= 0\")\n\t}\n\tif item.Concurrency < 0 {\n\t\treturn errors.New(\"concurrency must be >= 0\")\n\t}\n\tif item.Priority < 0 {\n\t\treturn errors.New(\"priority must be >= 0\")\n\t}\n\treturn nil\n}\n\nfunc defaultProxyName(name string) string {\n\tif strings.TrimSpace(name) == \"\" {\n\t\treturn \"imported-proxy\"\n\t}\n\treturn name\n}\n\n// enrichCredentialsFromIDToken performs best-effort extraction of user info fields\n// (email, plan_type, chatgpt_account_id, etc.) from id_token in credentials.\n// Only applies to OpenAI OAuth accounts. Skips expired token errors silently.\n// Existing credential values are never overwritten — only missing fields are filled.","sourceCodeStart":682,"sourceCodeEnd":718,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/backend/internal/handler/admin/account_data.go#L682-L718","documentation":"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.","triggerScenarios":"An account entry with \"concurrency\": -1 or lower; computed concurrency from capacity math that underflowed; conventions where -1 means unlimited colliding with this schema.","commonSituations":"Importing from a system that uses -1 for unlimited; spreadsheet or UI inputs allowing negatives; decimal values like 0.5 truncated oddly.","solutions":["Set concurrency to 0 (use default) or a positive integer; remove the field to omit it.","Map 'unlimited' from source systems to the platform's supported max or just omit the field.","Add min=0 constraint in the form/spreadsheet that produces the value."],"exampleFix":"// before\n{ \"name\": \"main\", \"platform\": \"openai\", \"type\": \"oauth\", \"credentials\": { ... }, \"concurrency\": -1 }\n\n// after\n{ \"name\": \"main\", \"platform\": \"openai\", \"type\": \"oauth\", \"credentials\": { ... }, \"concurrency\": 0 }","handlingStrategy":"validation","validationCode":"function hasValidConcurrency(entry: Record<string, unknown>): boolean {\n  const c = entry.concurrency\n  return c === undefined || c === null || (typeof c === 'number' && Number.isInteger(c) && c >= 0)\n}","typeGuard":"function isOptionalNonNegativeInt(n: unknown): n is number | undefined {\n  return n === undefined || n === null || (typeof n === 'number' && Number.isInteger(n) && n >= 0)\n}","tryCatchPattern":null,"preventionTips":["Map 'unlimited' (-1) from source systems to 0 or omit the field — this schema has no negative sentinel.","Use integer inputs with min=0 in forms and spreadsheets.","Note the sibling checks: rate_multiplier and priority follow the same non-negative rule."],"tags":["admin","import","account","validation","backend","numeric","concurrency"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}