Skip to main content
If your QR codes aren’t rendering, saving, or generating as expected, the sections below cover the most common root causes and their fixes. Each issue includes a concise diagnostic step and a working solution you can apply immediately.
If your problem isn’t listed here, open a GitHub issue and include your PHP version, Laravel version, the QR code method you called, and the full error message or stack trace. Those four details dramatically speed up diagnosis.

Common Issues

Symptom: The QR code shows as a literal escaped string like <svg ...> or a blank area instead of the actual image.Cause: Blade’s {{ }} syntax HTML-escapes its output. QR codes returned as SVG or raw binary must not be escaped.Fix — unescaped echo syntax:
Alternative — use the Blade component instead:The <x-qr-code> component handles output escaping automatically and is the recommended approach for Blade templates:
Symptom: An exception is thrown when you call ->format('png')->generate(...) or ->format('webp')->generate(...). SVG generation works fine.Cause: PNG and WebP rasterisation requires either the ext-imagick or ext-gd PHP extension. If neither is available, the renderer has no way to produce a bitmap image.Fix — verify your extensions:Run the following in your project to see which extensions are loaded:
Or check phpinfo() in a browser request and search for “imagick” or “gd”.
  • Install Imagick (recommended): Follow your system’s package manager instructions, e.g. sudo apt install php-imagick on Ubuntu, then restart PHP-FPM.
  • Install GD: Most PHP distributions include GD by default. Enable it in php.ini by uncommenting extension=gd.
Once at least one extension is active, PNG and WebP generation will work automatically.
Symptom: CannotWriteFileException (or a generic PHP warning) when you pass a $filename argument to generate().Cause: The target directory does not exist, or the web server process does not have write permission to it.Fix — create the directory and confirm permissions:
On a Linux server, also confirm the web server user (typically www-data) owns or has write access to the directory:
Symptom: The QR code generates successfully but scanners struggle or refuse to read it. The code looks extremely dense.Cause: QR codes have a finite data capacity. Long strings, high error correction levels, and small physical sizes all reduce scannability.Fix — reduce data and increase size with high error correction:
Guidelines:
  • Keep the data payload as short as possible. Encode an ID or short URL, not a full JSON blob.
  • Use errorCorrection('H') (30 % recovery) for codes that will be printed small or on uneven surfaces.
  • Set size() to at least 400 when using H error correction.
  • For extremely long data, consider storing it server-side and encoding only a lookup key.
Symptom: An InvalidArgumentException is thrown when calling a data-type method like WiFi(), PhoneNumber(), Email(), or VCard().Cause: Since v2.0, all data types validate their inputs strictly. Passing malformed data (wrong keys, missing required fields, bad phone format, etc.) throws an exception instead of silently generating a broken QR code.Fix — validate user input before passing it in:
Always run $request->validate(...) or equivalent before passing user-supplied values to any data-type method.
Symptom: The package uses Imagick for PNG/WebP rendering, but you need to use GD — for example, because your Imagick build has a known bug, or your deployment environment restricts Imagick.Cause: By default, the package prefers Imagick over GD when both are available.Fix — set the environment variable or config key:In your .env file:
Or, if you have published config/qrcode.php, set the key directly:
With either setting in place, the package always uses GD for bitmap rendering, even when Imagick is installed.
Symptom: You published config/qrcode.php and changed defaults like size, format, or error_correction, but generated QR codes still use the old values.Cause: Config-driven defaults are injected only when the Generator is resolved through Laravel’s service container — via the QrCode facade, the <x-qr-code> Blade component, or constructor injection. If you instantiate Generator manually with new Generator(), it receives the hardcoded package defaults, not your published config.Fix — use the facade or container injection:
After changing config/qrcode.php, clear the config cache so Laravel picks up your edits: