charmbracelet/crush · error

oauth token is nil

Error message

oauth token is nil

What it means

SetProviderAPIKey accepts *oauth.Token for OAuth providers. A typed-nil *oauth.Token passed as the apiKey carries no credential data, so the client rejects it before making any network request.

Source

Thrown at internal/client/config.go:99

// format tags the credential with an explicit Kind so the server can
// decode it back into the right Go type — JSON's `any` loses that
// information across the socket.
func (c *Client) SetProviderAPIKey(ctx context.Context, id string, scope config.Scope, providerID string, apiKey any) error {
	var (
		kind proto.APIKeyKind
		raw  json.RawMessage
	)
	switch v := apiKey.(type) {
	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 {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check the OAuth token is non-nil before calling SetProviderAPIKey
  2. If authentication failed, propagate that error instead of passing a nil token
  3. Pass a string API key instead if the provider uses a plain key

Example fix

// before
tok := loadToken() // may return nil
client.SetProviderAPIKey(ctx, wsID, scope, providerID, tok)
// after
tok := loadToken()
if tok == nil {
    return errors.New("no oauth token available")
}
client.SetProviderAPIKey(ctx, wsID, scope, providerID, tok)
Defensive patterns

Strategy: validation

Validate before calling

if tok, ok := apiKey.(*oauth.Token); ok && tok == nil {
    return errors.New("cannot set provider key: oauth token is nil")
}

Type guard

func isUsableKey(key any) bool {
    switch v := key.(type) {
    case string:
        return v != ""
    case *oauth.Token:
        return v != nil
    default:
        return false
    }
}

Prevention

When it happens

Trigger: Calling SetProviderAPIKey(ctx, wsID, scope, providerID, (*oauth.Token)(nil)) — the type switch matches *oauth.Token but v == nil.

Common situations: A token-loading function returned (nil, nil) and the caller forwarded the nil token without checking; a variable declared as *oauth.Token but never assigned.

Related errors


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