chenhg5/cc-connect · error

no OPENAI_API_KEY found

Error message

no OPENAI_API_KEY found

What it means

convertCodexProvider builds a Codex provider entry from cc-switch data. After applying the config TOML (base_url, model), it requires an API key; if p.APIKey is still empty it refuses to return a usable provider and returns this error. It exists so a Codex provider without credentials is never silently used.

Source

Thrown at cmd/cc-connect/provider.go:417

	}
	return p, nil
}

func convertCodexProvider(p config.ProviderConfig, sc map[string]any) (config.ProviderConfig, error) {
	// API key from auth.OPENAI_API_KEY
	if auth, ok := sc["auth"].(map[string]any); ok {
		if key, ok := auth["OPENAI_API_KEY"].(string); ok && key != "" {
			p.APIKey = key
		}
	}

	// base_url and model from config TOML string
	if cfgStr, ok := sc["config"].(string); ok && cfgStr != "" {
		p.BaseURL, p.Model = parseCodexConfigTOML(cfgStr)
	}

	if p.APIKey == "" {
		return p, fmt.Errorf("no OPENAI_API_KEY found")
	}
	return p, nil
}

// parseCodexConfigTOML extracts base_url and model from a Codex config.toml string.
// It handles both flat `base_url = "..."` and upstream-style `[model_providers.X]` sections.
func parseCodexConfigTOML(cfgStr string) (baseURL, model string) {
	for _, line := range strings.Split(cfgStr, "\n") {
		line = strings.TrimSpace(line)
		if k, v, ok := parseTOMLKV(line); ok {
			switch k {
			case "base_url":
				if baseURL == "" {
					baseURL = v
				}
			case "model":
				if model == "" {
					model = v

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Open the provider entry in cc-switch (or its settings JSON) and set the OpenAI API key field.
  2. Export OPENAI_API_KEY in the environment cc-connect runs under if the provider is meant to inherit it.
  3. Re-import the provider from a complete config.toml that includes the key, then retry.

Example fix

// before (provider settings in cc-switch)
{ "name": "my-provider", "config": "model_provider = ..." }
// after
{ "name": "my-provider", "apiKey": "sk-...", "config": "model_provider = ..." }
Defensive patterns

Strategy: validation

Validate before calling

if apiKey, _ := prov["apiKey"].(string); strings.TrimSpace(apiKey) == "" {
    return fmt.Errorf("provider %q has no OPENAI_API_KEY; set it in cc-switch before use", prov["name"])
}

Type guard

apiKey, ok := sc["apiKey"].(string); if !ok || strings.TrimSpace(apiKey) == "" { /* treat as unconfigured */ }

Try / catch

p, err := convertCCSwitchProvider(rec)
if err != nil {
    if strings.Contains(err.Error(), "no OPENAI_API_KEY") {
        slog.Warn("skipping provider without API key", "provider", rec.Name)
        return
    }
    return err
}

Prevention

When it happens

Trigger: Calling convertCCSwitchProvider/convertCodexProvider with a provider record whose api key field (OPENAI_API_KEY / apiKey in the cc-switch DB or settings JSON) is missing or empty.

Common situations: User imported a provider into cc-switch but never filled in OPENAI_API_KEY; key stored under an unexpected JSON key so parsing misses it; provider uses only env-var auth (e.g. ChatGPT login) with no explicit key.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/202c8ab7059cf038. Report an issue: GitHub.