Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Symfony Ignition Bundle Laravel Package

spatie/symfony-ignition-bundle

Spatie Symfony Ignition Bundle replaces Symfony’s default exception pages with Ignition’s beautiful, customizable error pages, including dark mode. Install via Composer as a dev dependency and enable the bundle in config/bundles.php.

View on GitHub
Deep Wiki
Context7

Getting Started

Ignition swaps Symfony's dev exception page for the same renderer Laravel uses: stack frames with code excerpts, request/route context, and (optionally) AI-generated fix suggestions. It is a dev-only tool — install it and forget it exists in production.

composer require --dev spatie/symfony-ignition-bundle

Register it for dev only, in config/bundles.php:

return [
    // ...
    Spatie\SymfonyIgnitionBundle\IgnitionBundle::class => ['dev' => true],
];

Since 1.0.0 the Symfony Flex recipe is approved, so a fresh composer require into a Flex app typically writes both the bundle entry and config/packages/ignition.yaml for you — verify before hand-editing.

Where to look first: bin/console debug:config ignition is the authoritative list of keys this bundle actually exposes. Treat the README snippet as an example, not the full surface.

Baseline config:

# config/packages/ignition.yaml
when@dev:
    ignition:
        application_path: '%kernel.project_dir%'
        dark_mode: false
        should_display_exception: '%kernel.debug%'
        force_html_response: false

First use case: throw something and hit the route.

#[Route('/orders/{id}', name: 'order_show')]
public function show(int $id, OrderRepository $orders): Response
{
    $order = $orders->find($id) ?? throw new \RuntimeException("No order {$id}");
    // ...
}

You get the Ignition page instead of Symfony's. If you don't, the exception is almost certainly being thrown before the kernel.exception event fires (see Gotchas) or the bundle isn't enabled for the current env.

Requirements worth checking up front: PHP 8.1+ (8.0 dropped in 1.1.0), Symfony 6.1+/7.x, and 1.3.1 or later if you're on Symfony 8.

Implementation Patterns

Scope configuration to dev, always. The when@dev wrapper plus ['dev' => true] in bundles.php is belt-and-braces; keep both. If you also want it in test, add 'test' => true deliberately — not by default, because HTML error bodies can break JSON assertions in functional tests.

Make the request format work for you. Since 1.3.0, non-HTML requests pass through to Symfony's normal handling. That's the right default for a JSON API. When you're debugging a fetch/Axios call from a SPA and want the full Ignition page in the browser tab, flip it temporarily:

when@dev:
    ignition:
        force_html_response: true

Keep it false in your committed config and toggle it locally, otherwise you'll get HTML injected into API responses your frontend tries to JSON.parse, and you'll chase a phantom "unexpected token <" bug.

Point application_path at the root your code actually lives at. In Docker, a monorepo, or a DDEV setup where %kernel.project_dir% differs from the path baked into stack traces, source excerpts and frame collapsing get it wrong. Setting it explicitly to the mount point fixes both.

AI solutions, safely. openai_key enables the "solve with AI" affordance:

when@dev:
    ignition:
        openai_key: '%env(OPENAI_API_KEY)%'

Keep the key in .env.local (gitignored) or a developer's shell environment, never in .env or the committed YAML. Note the privacy implication: the stack trace and surrounding source lines leave your machine. On client work or anything under NDA, leave the key unset — everything else in Ignition works without it.

Use it as your primary "why did this break?" loop. The practical workflow that replaces tail -f var/log/dev.log:

  1. Reproduce in the browser.
  2. Read the exception message and the highlighted application frame — Ignition separates your frames from vendor noise.
  3. Inspect request/route/query context on the same page instead of re-running with dump().
  4. Only drop to dump()/dd (or bin/console + profiler) for state that isn't in the exception context.

Pair it with the profiler rather than instead of it. Ignition renders the exception response; the Symfony profiler still records the request. For an exception you keep hitting, open the profiler's Exception panel for the full trace and the Logs panel for deprecations that Ignition won't surface.

Custom error pages stay testable in test/prod. Because the bundle is dev-only, your templates/bundles/TwigBundle/Exception/error404.html.twig and custom framework.error_controller are exercised only outside dev. Run your error-page tests with APP_ENV=test and APP_DEBUG=0; if you enable Ignition in test, those tests will assert against Ignition's HTML and pass for the wrong reason.

Gotchas and Tips

  • CLI errors are untouched. bin/console failures still render Symfony's console error output. If you're debugging a failing command, Ignition will not help; use -vvv and the log.
  • Boot-time and container errors bypass it. Exceptions thrown while the kernel boots, during container compilation, or in a kernel.exception listener with a higher priority than Ignition's won't reach the renderer. Symptom: "Ignition worked all morning, now I get the plain Symfony page." Run bin/console cache:clear and check var/log/dev.log — the broken thing is usually a service definition or an env var, not Ignition.
  • should_display_exception: '%kernel.debug%' is load-bearing. With APP_DEBUG=0 you'll get the generic page even in dev. If a colleague's .env.local sets APP_DEBUG=0, Ignition silently looks broken.
  • The bundle exposes a subset of Ignition's options. Things documented in spatie/ignition's own README — Flare reporting keys, custom solution providers, housekeeping — are not all plumbed through ignition.yaml. Confirm against debug:config ignition before assuming a key is supported, and reach for the underlying Ignition configuration (or a small compiler pass / listener) if you need more.
  • Your own exception listener may be shadowed. Ignition converts the exception into a Response; any listener you wrote that also builds a response for HTML requests in dev will compete on priority. Verify custom error handling in test, and don't judge it by what dev shows you.
  • Production safety checklist: composer install --no-dev in the build image, bundle registered for dev only, and no openai_key in any committed file. Because the dependency is require-dev, a --no-dev install makes it structurally impossible to leak the error page — that's the real guarantee.
  • Docker/CI source excerpts. The code preview reads files from disk. On a read-only filesystem or when application_path doesn't resolve inside the container, frames render without excerpts. Not fatal, but confusing.
  • Config changes need a cache clear. bin/console cache:clear after editing ignition.yaml; the bundle's config is compiled into the container like any other.
  • Maturity signal. Small install base (29 stars, no dependents) and a changelog dominated by dependency bumps — but it's Spatie-maintained, has a Flex recipe, and the last releases track Symfony 8. Pin a version, keep it in require-dev, and it's a low-risk convenience rather than infrastructure.
  • Extension points, if you outgrow the YAML: the bundle's whole job is registering Ignition's renderer on the kernel.exception event. Custom behavior — extra context, your own solution providers, tab additions — belongs in a service tagged for Ignition's run-time config or a small listener registered after it, not in forking the bundle.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource