{"record":{"id":"5598eaecb8f84c04","repo":"Wei-Shaw/sub2api","slug":"account-credentials-is-required","errorCode":null,"errorMessage":"account credentials is required","messagePattern":"account credentials is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/internal/handler/admin/account_data.go","lineNumber":689,"sourceCode":"\t\tif normalizedStatus != service.StatusActive && normalizedStatus != \"inactive\" {\n\t\t\treturn fmt.Errorf(\"proxy status is invalid: %s\", item.Status)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validateDataAccount(item DataAccount) error {\n\tif strings.TrimSpace(item.Name) == \"\" {\n\t\treturn errors.New(\"account name is required\")\n\t}\n\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","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/backend/internal/handler/admin/account_data.go#L671-L707","documentation":"Returned by validateDataAccount (backend/internal/handler/admin/account_data.go:689) when an accounts[] entry has name, platform, and a valid type but an empty or absent credentials map (len(item.Credentials) == 0). Credentials carries the account's secrets (tokens, API keys) and is required regardless of type.","triggerScenarios":"An account object with \"credentials\": {} or no credentials key; credentials sent as null; a nested structure that failed to unmarshal into map[string]string leaving it empty.","commonSituations":"Stripping secrets before sharing an export then re-importing it; serializers omitting empty maps; credentials stored under a different key (e.g. 'secrets').","solutions":["Populate credentials with at least one key/value appropriate to the type (e.g. access_token for oauth, api_key for api_key).","If credentials were removed for sharing, re-add them before import or use the redacted-export flow if one exists.","Confirm the field is a JSON object of strings, not null."],"exampleFix":"// before\n{ \"name\": \"main\", \"platform\": \"openai\", \"type\": \"api_key\", \"credentials\": {} }\n\n// after\n{ \"name\": \"main\", \"platform\": \"openai\", \"type\": \"api_key\", \"credentials\": { \"api_key\": \"sk-...\" } }","handlingStrategy":"validation","validationCode":"function hasCredentials(entry: Record<string, unknown>): boolean {\n  const c = entry.credentials\n  return typeof c === 'object' && c !== null && !Array.isArray(c) && Object.keys(c).length > 0 &&\n    Object.values(c).every((v) => typeof v === 'string')\n}","typeGuard":"function isNonEmptyCredentials(c: unknown): c is Record<string, string> {\n  if (typeof c !== 'object' || c === null || Array.isArray(c)) return false\n  const o = c as Record<string, unknown>\n  return Object.keys(o).length > 0 && Object.values(o).every((v) => typeof v === 'string')\n}","tryCatchPattern":null,"preventionTips":["Never import redacted/secret-stripped exports; keep credentials in the payload.","Serialize credentials as a flat string map (JSON object of strings).","Check each entry's credentials is present and non-empty before submit."],"tags":["admin","import","account","credentials","validation","backend"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}