coollabsio/coolify · info · RuntimeException

Unhandled event type: {$type}

Error message

Unhandled event type: {$type}

What it means

The switch in StripeProcessJob covers a fixed set of Stripe event types (radar.early_fraud_warning.created, checkout.session.completed, invoice.paid, invoice.payment_failed, payment_intent.payment_failed, customer.subscription.created/updated/deleted). Any event type outside that set falls through to the default branch and throws this RuntimeException. The catch block turns it into an internal notification, so the job finishes - it signals that Stripe sent an event Coolify does not act on.

Source

Thrown at app/Jobs/StripeProcessJob.php:345

                case 'customer.subscription.deleted':
                    $customerId = data_get($data, 'customer');
                    $subscriptionId = data_get($data, 'id');
                    $subscription = Subscription::where('stripe_customer_id', $customerId)->where('stripe_subscription_id', $subscriptionId)->first();
                    if ($subscription) {
                        $team = data_get($subscription, 'team');
                        if ($team) {
                            $team->subscriptionEnded();
                        } else {
                            // send_internal_notification('Subscription deleted but no team found in Coolify for customer: '.$customerId);
                            throw new \RuntimeException("No team found in Coolify for customer: {$customerId}");
                        }
                    } else {
                        // send_internal_notification('Subscription deleted but no subscription found in Coolify for customer: '.$customerId);
                        break;
                    }
                    break;
                default:
                    throw new \RuntimeException("Unhandled event type: {$type}");
            }
        } catch (\Exception $e) {
            send_internal_notification('StripeProcessJob error: '.$e->getMessage());
        }
    }
}

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Read the internal notification to see the exact event type; if it is irrelevant to Coolify (e.g. invoice or customer events), restrict the webhook in the Stripe dashboard to only the event types Coolify handles
  2. If the event matters for billing state, update Coolify - a newer release may handle it - or add a `case` for the type in StripeProcessJob
  3. No action if benign: the throw is already caught and only notifies
Defensive patterns

Strategy: validation

Validate before calling

// filter at the webhook controller before dispatching the job
$handled = [
    'radar.early_fraud_warning.created',
    'checkout.session.completed',
    'invoice.paid',
    'invoice.payment_failed',
    'payment_intent.payment_failed',
    'customer.subscription.created',
    'customer.subscription.updated',
    'customer.subscription.deleted',
];
if (! in_array($event->type, $handled, true)) {
    return response()->json(['ignored' => $event->type]); // ack so Stripe stops retrying
}

Prevention

When it happens

Trigger: The Stripe webhook endpoint receives an event type with no matching `case`, e.g. `invoice.payment_succeeded`, `customer.updated`, or any type introduced by a Stripe API version bump.

Common situations: The webhook endpoint in Stripe configured to send all events instead of only the types Coolify subscribes to; Stripe API version upgrades introducing new event types; manually sent test events from the Stripe dashboard.


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/c79db61b9276ea6f. Report an issue: GitHub.