charmbracelet/crush · error

unsupported api key type %T

Error message

unsupported api key type %T

What it means

SetProviderAPIKey only accepts string or *oauth.Token API keys. Any other type (int, []byte, custom struct, untyped nil interface) hits the default branch and is rejected locally before any HTTP request is made, with the offending type printed via %T.

Source

Thrown at internal/client/config.go:108

	case string:
		kind = proto.APIKeyKindString
		b, err := json.Marshal(v)
		if err != nil {
			return fmt.Errorf("failed to marshal api key string: %w", err)
		}
		raw = b
	case *oauth.Token:
		if v == nil {
			return fmt.Errorf("oauth token is nil")
		}
		kind = proto.APIKeyKindOAuth
		b, err := json.Marshal(v)
		if err != nil {
			return fmt.Errorf("failed to marshal oauth token: %w", err)
		}
		raw = b
	default:
		return fmt.Errorf("unsupported api key type %T", apiKey)
	}

	rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/config/provider-key", id), nil, jsonBody(proto.ConfigProviderKeyRequest{
		Scope:      scope,
		ProviderID: providerID,
		Kind:       kind,
		APIKey:     raw,
	}), http.Header{"Content-Type": []string{"application/json"}})
	if err != nil {
		return fmt.Errorf("failed to set provider API key: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return fmt.Errorf("failed to set provider API key: status code %d", rsp.StatusCode)
	}
	return nil
}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Convert the credential: string(byteKey) for []byte values
  2. Load an *oauth.Token for OAuth providers before calling
  3. Check the error's %T suffix to see which type was actually passed

Example fix

// before
key := cfg.GetProviderKeyBytes(providerID) // []byte
client.SetProviderAPIKey(ctx, wsID, scope, providerID, key)
// after
client.SetProviderAPIKey(ctx, wsID, scope, providerID, string(key))
Defensive patterns

Strategy: type-guard

Type guard

func normalizeAPIKey(key any) (any, bool) {
    switch v := key.(type) {
    case string:
        return v, true
    case *oauth.Token:
        return v, v != nil
    case []byte:
        return string(v), true
    default:
        return nil, false
    }
}

Prevention

When it happens

Trigger: Calling SetProviderAPIKey with apiKey of any type other than string or *oauth.Token, e.g. passing []byte(key), a keyring handle, or a bare nil interface.

Common situations: Refactored code after a version change where the signature narrowed to string | *oauth.Token; reading a key from a store that returns []byte; passing nil interface directly.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/40d9907a5fb80c05. Report an issue: GitHub.