{"record":{"id":"1600c1eb922e6fc2","repo":"Wei-Shaw/sub2api","slug":"error","errorCode":null,"errorMessage":"导入项为空","messagePattern":"导入项为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/internal/handler/admin/account_codex_import.go","lineNumber":776,"sourceCode":"}\n\nfunc buildCodexCreateAccountName(base string, item *codexImportAccount, index, total int) string {\n\tbase = strings.TrimSpace(base)\n\tif base == \"\" {\n\t\tif item == nil {\n\t\t\treturn fmt.Sprintf(\"Codex 导入账号 %d\", index)\n\t\t}\n\t\treturn item.Name\n\t}\n\tif total > 1 {\n\t\treturn fmt.Sprintf(\"%s #%d\", base, index)\n\t}\n\treturn base\n}\n\nfunc resolveCodexImportExpiry(req CodexSessionImportRequest, item *codexImportAccount) (*int64, *time.Time, *bool, []string, error) {\n\tif item == nil {\n\t\treturn nil, nil, nil, nil, errors.New(\"导入项为空\")\n\t}\n\t// Agent Identity has no OAuth access-token lifetime. Its runtime/task\n\t// lifecycle is handled by the upstream task recovery path, so it must not\n\t// be rejected or auto-paused by the OAuth import expiry policy.\n\tif item.IsAgentIdentity {\n\t\treturn nil, nil, nil, nil, nil\n\t}\n\n\tvar requestExpiresAt *time.Time\n\tif req.ExpiresAt != nil && *req.ExpiresAt > 0 {\n\t\tt := time.Unix(*req.ExpiresAt, 0).UTC()\n\t\trequestExpiresAt = &t\n\t}\n\n\tvar accountExpiresAt *time.Time\n\tvar credentialExpiresAt *time.Time\n\twarnings := make([]string, 0, 2)\n\tif item.RefreshToken == \"\" {","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/backend/internal/handler/admin/account_codex_import.go#L758-L794","documentation":"Returned by resolveCodexImportExpiry (backend/internal/handler/admin/account_codex_import.go:776) when called with a nil *codexImportAccount. It is a defensive precondition: every import item must be materialized before expiry resolution. Agent-identity items legitimately return all-nil results (no OAuth lifetime), but a nil item is always a bug in the caller loop, not a user input problem.","triggerScenarios":"An import loop passing a nil slice element or a failed/never-constructed codexImportAccount into resolveCodexImportExpiry; a refactor that made the item constructor return nil on a path that was not checked.","commonSituations":"Code changes in the import handler that skip item construction on parse errors but still call expiry resolution; a nil pointer after an earlier error return was removed; concurrent mutation of the items slice.","solutions":["If you are modifying the import handler, ensure items are appended only when non-nil and that error paths return before expiry resolution.","Audit the caller loop for indexes into a slice that can contain nils (e.g. preallocated make([]*codexImportAccount, n) never fully filled).","As an operator this error indicates a backend bug — report it with the payload shape rather than retrying the same input."],"exampleFix":"// before\naccounts := make([]*codexImportAccount, len(raw))\nfor i, r := range raw {\n  if err := fill(r, accounts[i]); err != nil { continue } // leaves nils\n  resolveCodexImportExpiry(req, accounts[i])\n}\n\n// after\nvar accounts []*codexImportAccount\nfor _, r := range raw {\n  item, err := buildItem(r)\n  if err != nil { return err }\n  accounts = append(accounts, item)\n  resolveCodexImportExpiry(req, item)\n}","handlingStrategy":"validation","validationCode":"// before calling resolveCodexImportExpiry:\nif item == nil {\n    return errors.New(\"internal: import item not constructed\")\n}\nexp, credExp, autoPause, warns, err := resolveCodexImportExpiry(req, item)","typeGuard":null,"tryCatchPattern":"if item == nil {\n    if _, _, _, _, err := resolveCodexImportExpiry(req, item); err != nil {\n        // defensive tripwire: log with stack, this is a code bug not user input\n        log.Printf(\"BUG: resolveCodexImportExpiry called with nil item: %+v\", err)\n    }\n}","preventionTips":["Append to a []*codexImportAccount only after successful construction; never preallocate and partially fill.","Return on item-build errors instead of continuing the loop with nil entries.","Treat this error in production as a backend bug — capture the payload shape and report it."],"tags":["backend","import","nil-guard","defensive","codex"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}