{"record":{"id":"e2d8237717b9a1c7","repo":"Wei-Shaw/sub2api","slug":"account-name-is-required","errorCode":null,"errorMessage":"account name is required","messagePattern":"account name is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/internal/handler/admin/account_data.go","lineNumber":680,"sourceCode":"\t\treturn errors.New(\"proxy port is invalid\")\n\t}\n\tswitch item.Protocol {\n\tcase \"http\", \"https\", \"socks5\", \"socks5h\":\n\tdefault:\n\t\treturn fmt.Errorf(\"proxy protocol is invalid: %s\", item.Protocol)\n\t}\n\tif item.Status != \"\" {\n\t\tnormalizedStatus := normalizeProxyStatus(item.Status)\n\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}","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/backend/internal/handler/admin/account_data.go#L662-L698","documentation":"Returned by validateDataAccount (backend/internal/handler/admin/account_data.go:680) when an accounts[] entry's name is empty after TrimSpace. Name is the first per-account field checked, followed by platform, type, and credentials, so this error means the entry failed at the very first precondition.","triggerScenarios":"An account object with name missing, blank, or whitespace-only; a serializer dropping the name field for auto-named accounts.","commonSituations":"Minimal hand-written imports that skip display names; exports where name was optional; front-end form allowing empty name.","solutions":["Set a non-empty name on every account entry (e.g. 'openai-main').","If generating payloads, always emit a name — the import does not auto-generate one.","Trim and check required fields client-side before submit."],"exampleFix":"// before\n{ \"platform\": \"openai\", \"type\": \"oauth\", \"credentials\": { ... } }\n\n// after\n{ \"name\": \"openai-main\", \"platform\": \"openai\", \"type\": \"oauth\", \"credentials\": { ... } }","handlingStrategy":"validation","validationCode":"function hasAccountName(entry: Record<string, unknown>): boolean {\n  return typeof entry.name === 'string' && entry.name.trim() !== ''\n}","typeGuard":"function hasRequiredAccountStrings(e: unknown, keys: string[]): e is Record<string, string> {\n  if (typeof e !== 'object' || e === null) return false\n  const o = e as Record<string, unknown>\n  return keys.every((k) => typeof o[k] === 'string' && (o[k] as string).trim() !== '')\n}","tryCatchPattern":null,"preventionTips":["Generate a name (e.g. 'imported-account-N') when the source lacks one — the import does not auto-name.","Require name/platform/type in the import UI.","Trim all string fields before submit."],"tags":["admin","import","account","validation","backend"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}