{"record":{"id":"329addb4f021c99c","repo":"chenhg5/cc-connect","slug":"no-api-key-or-env-found","errorCode":null,"errorMessage":"no API key or env found","messagePattern":"no API key or env found","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cc-connect/provider.go","lineNumber":398,"sourceCode":"\t\tp.Model = model\n\t}\n\n\t// Carry over any extra env vars (e.g. ANTHROPIC_DEFAULT_HAIKU_MODEL)\n\textra := make(map[string]string)\n\tknown := map[string]bool{\"ANTHROPIC_AUTH_TOKEN\": true, \"ANTHROPIC_BASE_URL\": true, \"ANTHROPIC_MODEL\": true}\n\tfor k, v := range env {\n\t\tif !known[k] {\n\t\t\tif s, ok := v.(string); ok && s != \"\" {\n\t\t\t\textra[k] = s\n\t\t\t}\n\t\t}\n\t}\n\tif len(extra) > 0 {\n\t\tp.Env = extra\n\t}\n\n\tif p.APIKey == \"\" && len(p.Env) == 0 {\n\t\treturn p, fmt.Errorf(\"no API key or env found\")\n\t}\n\treturn p, nil\n}\n\nfunc convertCodexProvider(p config.ProviderConfig, sc map[string]any) (config.ProviderConfig, error) {\n\t// API key from auth.OPENAI_API_KEY\n\tif auth, ok := sc[\"auth\"].(map[string]any); ok {\n\t\tif key, ok := auth[\"OPENAI_API_KEY\"].(string); ok && key != \"\" {\n\t\t\tp.APIKey = key\n\t\t}\n\t}\n\n\t// base_url and model from config TOML string\n\tif cfgStr, ok := sc[\"config\"].(string); ok && cfgStr != \"\" {\n\t\tp.BaseURL, p.Model = parseCodexConfigTOML(cfgStr)\n\t}\n\n\tif p.APIKey == \"\" {","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/cmd/cc-connect/provider.go#L380-L416","documentation":"After extracting the API key and any extra env vars from a claude provider's settings_config, convertClaudeProvider verifies at least one usable credential was found. If p.APIKey is empty AND p.Env is empty, the row carries no authentication information at all, so the conversion fails with this error. Importing such a provider would yield a config entry that cannot authenticate.","triggerScenarios":"settings_config has an `env` object but it contains neither ANTHROPIC_AUTH_TOKEN (empty or absent) nor any other recognized env entries — e.g. {\"env\":{\"OTHER_VAR\":\"x\"}} or {\"env\":{}}.","commonSituations":"Placeholder tokens left empty in cc-switch; provider rows where the token was stored under a differently-named env var; redacted/stripped settings after a sanitizing export.","solutions":["Set ANTHROPIC_AUTH_TOKEN in the row's env object (or ANTHROPIC_API_KEY if your cc-switch uses it).","Verify the env object is non-empty and the key name matches exactly what the converter reads.","Re-enter the API key in the cc-switch UI and re-import.","Skip rows with no credentials instead of failing the whole import."],"exampleFix":"// before\n{\"env\": {}}\n// error: no API key or env found\n// after\n{\"env\": {\"ANTHROPIC_AUTH_TOKEN\": \"sk-ant-...\"}}","handlingStrategy":"validation","validationCode":"func hasClaudeCredentials(settingsJSON string) bool {\n    var sc struct { Env map[string]string `json:\"env\"` }\n    if json.Unmarshal([]byte(settingsJSON), &sc) != nil { return false }\n    return sc.Env[\"ANTHROPIC_AUTH_TOKEN\"] != \"\" || sc.Env[\"ANTHROPIC_API_KEY\"] != \"\"\n}","typeGuard":"if p.APIKey == \"\" && len(p.Env) == 0 {\n    return p, fmt.Errorf(\"no API key or env found\")\n}","tryCatchPattern":"p, err := convertCCSwitchProvider(row)\nif err != nil && strings.Contains(err.Error(), \"no API key or env found\") {\n    slog.Warn(\"provider row carries no credentials; skipping\", \"name\", row.Name)\n    continue\n}","preventionTips":["Fill in ANTHROPIC_AUTH_TOKEN in cc-switch before importing providers.","Verify the env object contains at least one recognized auth variable.","Re-enter keys in the cc-switch UI if a sanitized export stripped them.","Skip credential-less rows so one bad provider does not block the batch."],"tags":["go","cc-switch","credentials","claude"],"backgroundTag":"missing-api-key","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}