Wei-Shaw/sub2api · error
agent identity 缺少必要字段
Error message
agent identity 缺少必要字段
What it means
Returned while normalizing an agent-identity entry in the Codex import (backend/internal/handler/admin/account_codex_import.go:519) when any of the four mandatory fields is missing after snake_case/camelCase lookup: agent_runtime_id, agent_private_key, account_id, or chatgpt_user_id (item.AgentRuntimeID, item.AgentPrivateKey, item.AccountID, item.UserID). Optional fields like task_id and email do not trigger it. The check runs only for entries flagged IsAgentIdentity=true.
Source
Thrown at backend/internal/handler/admin/account_codex_import.go:519
switch raw := entry.Value.(type) {
case string:
item.AccessToken = strings.TrimSpace(raw)
case map[string]any:
if agentIdentity, ok := firstCodexMap(raw, []string{"agent_identity"}, []string{"agentIdentity"}); ok || strings.EqualFold(firstCodexString(raw, []string{"auth_mode"}, []string{"authMode"}), service.OpenAIAuthModeAgentIdentity) {
if !ok {
agentIdentity = raw
}
item.IsAgentIdentity = true
item.AgentRuntimeID = firstCodexString(agentIdentity, []string{"agent_runtime_id"}, []string{"agentRuntimeId"})
item.AgentPrivateKey = firstCodexString(agentIdentity, []string{"agent_private_key"}, []string{"agentPrivateKey"})
item.AgentTaskID = firstCodexString(agentIdentity, []string{"task_id"}, []string{"taskId"})
item.AccountID = firstCodexString(agentIdentity, []string{"account_id"}, []string{"accountId"})
item.UserID = firstCodexString(agentIdentity, []string{"chatgpt_user_id"}, []string{"chatgptUserId"})
item.Email = firstCodexString(agentIdentity, []string{"email"})
item.PlanType = firstCodexString(agentIdentity, []string{"plan_type"}, []string{"planType"})
item.AgentFedRAMP = firstCodexBool(agentIdentity, []string{"chatgpt_account_is_fedramp"}, []string{"chatgptAccountIsFedramp"})
if item.AgentRuntimeID == "" || item.AgentPrivateKey == "" || item.AccountID == "" || item.UserID == "" {
return nil, errors.New("agent identity 缺少必要字段")
}
if err := service.ValidateOpenAIAgentIdentityPrivateKey(item.AgentPrivateKey); err != nil {
return nil, errors.New("agent identity private key 格式无效")
}
item.Credentials["auth_mode"] = service.OpenAIAuthModeAgentIdentity
item.Credentials["agent_runtime_id"] = item.AgentRuntimeID
item.Credentials["agent_private_key"] = item.AgentPrivateKey
item.Credentials["chatgpt_account_id"] = item.AccountID
item.Credentials["chatgpt_user_id"] = item.UserID
item.Credentials["chatgpt_account_is_fedramp"] = item.AgentFedRAMP
setCodexCredentialIfNotEmpty(item.Credentials, "task_id", item.AgentTaskID)
setCodexCredentialIfNotEmpty(item.Credentials, "email", item.Email)
setCodexCredentialIfNotEmpty(item.Credentials, "plan_type", item.PlanType)
if item.AgentTaskID == "" {
item.WarningTexts = append(item.WarningTexts, "未包含 task_id,首次请求会使用现有 runtime 注册新 task")
}
item.IdentityKeys = buildCodexAgentIdentityKeys(item.AccountID)
item.Name = buildCodexImportAccountName(item, entry.Index)View on GitHub (pinned to 073e92d171)
Solutions
- Ensure all four required keys exist and are non-empty strings: agent_runtime_id, agent_private_key, account_id, chatgpt_user_id (camelCase variants agentRuntimeId/agentPrivateKey/accountId/chatgptUserId also accepted).
- Check spelling/casing of keys — only the two documented spellings are recognized.
- If the JSON is nested, confirm the identity fields sit where the parser expects them, not one level off.
- If you meant a normal OAuth account, remove the agent-identity marker so the entry is not parsed as IsAgentIdentity.
Example fix
// before
{
"agent_runtime_id": "rt_123",
"agent_private_key": "",
"account_id": "acc_1",
"chatgpt_user_id": "user_1"
}
// after
{
"agent_runtime_id": "rt_123",
"agent_private_key": "-----BEGIN PRIVATE KEY-----...",
"account_id": "acc_1",
"chatgpt_user_id": "user_1",
"task_id": "task_9",
"email": "agent@example.com"
} Defensive patterns
Strategy: validation
Validate before calling
function hasAgentIdentityRequiredFields(identity: Record<string, unknown>): boolean {
const pick = (snake: string, camel: string) => {
const v = identity[snake] ?? identity[camel]
return typeof v === 'string' && v.length > 0
}
return (
pick('agent_runtime_id', 'agentRuntimeId') &&
pick('agent_private_key', 'agentPrivateKey') &&
pick('account_id', 'accountId') &&
pick('chatgpt_user_id', 'chatgptUserId')
)
} Type guard
function isCompleteAgentIdentity(v: unknown): v is { agent_runtime_id: string; agent_private_key: string; account_id: string; chatgpt_user_id: string } {
if (typeof v !== 'object' || v === null) return false
const o = v as Record<string, unknown>
return ['agent_runtime_id', 'agent_private_key', 'account_id', 'chatgpt_user_id'].every(
(k) => typeof o[k] === 'string' && (o[k] as string).length > 0
)
} Prevention
- Import the agent-identity file exactly as exported by the producing tool; avoid hand-editing.
- Use only the two accepted spellings per field (snake_case or the documented camelCase variant).
- Validate the four required keys in the admin UI before submit.
- Remember task_id and email are optional — their absence yields only a warning, not this error.
When it happens
Trigger: Importing an agent-identity JSON where agent_runtime_id, agent_private_key, account_id, or chatgpt_user_id is absent, null, empty, or misspelled so neither the snake_case nor camelCase key matches (e.g. 'runtimeId' instead of 'agentRuntimeId').
Common situations: Hand-editing an exported agent identity and dropping a field; upstream format change renaming keys; copying an example template with placeholders left blank; mixing agent-identity docs with regular OAuth auth.json and missing the nested identity object.
Related errors
- agent identity private key 格式无效
- 空 JSON 内容
- 缺少 accessToken/access_token
- 未包含 refresh_token,且无法解析 accessToken 过期时间;请在第一步设置过期时间后再导入
- proxies is required
AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15).
Data as JSON: /api/errors/0c029c93582d9f82.
Report an issue: GitHub.