Stop Error Tracking Sprawl: Keep Exception Messages Static

📖 2 minutes read

If you use Sentry (or any error tracking tool) with a Laravel app, you’ve probably noticed this problem: one error creates dozens of separate entries instead of grouping into one.

The culprit is almost always dynamic data in the exception message.

The Problem

// ❌ This creates a NEW error entry for every different order ID
throw new \RuntimeException(
    "Failed to sync pricing for order {$order->id}: API returned error {$response->error_code}"
);

Sentry groups issues by their stack trace and exception message. When the message changes with every occurrence — because it includes an ID, a timestamp, or an API reference code — each one becomes its own entry.

Instead of seeing “Failed to sync pricing — thousands of occurrences” neatly grouped, you get a wall of individual entries. Good luck triaging that.

The Fix

Keep exception messages static. Pass the dynamic parts as context instead:

// ✅ Static message — Sentry groups these together
throw new SyncFailedException(
    'Failed to sync pricing: API returned error',
    previous: $exception,
    context: [
        'order_id' => $order->id,
        'error_code' => $response->error_code,
        'error_ref' => $response->error_reference,
    ]
);

The dynamic data still gets captured — you can see it in Sentry’s event detail view. But since the message is identical across occurrences, they all group under one entry.

Using Sentry’s Context API

If you can’t change the exception class, use Sentry’s scope to attach context before the exception is captured:

use Sentry\State\Scope;

\Sentry\configureScope(function (Scope $scope) use ($order, $response) {
    $scope->setContext('sync_details', [
        'order_id' => $order->id,
        'error_code' => $response->error_code,
    ]);
});

throw new \RuntimeException('Pricing sync failed');

Or even simpler in Laravel, use report() with context in your exception handler:

try {
    $this->syncPricing($order);
} catch (ApiException $e) {
    report($e->setContext([
        'order_id' => $order->id,
    ]));
}

The Rule of Thumb

If you’re interpolating a variable into an exception message, ask yourself: will this string be different for each occurrence?

If yes — pull it out. Static messages, dynamic context. Your Sentry dashboard (and your on-call engineer at 3 AM) will thank you.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *