nicks's avatar

Laravel Horizon giving syntax error

I have newly installed Laravel Horizon v5.33.2. When I go to /horizon I get Uncaught SyntaxError: Unexpected token '<' (at horizon:31:27) in the console, and the page displays as a blank black page.

The problem appears to be a <br /> occuring within a <script> element:

    <script type="module"><br />
    window.Horizon = JSON.parse('{\u0022path\u0022:\u0022horizon\u0022,\u0022proxy_path\u0022:\u0022\u0022}');<br />
...

The Horizon installation is newly installed with no configuration changes in horizon.php or HorizonServiceProvider.php.

I am running Laravel v11.45.0 using Laravel Valet and PHP 8.3 on a Mac with InertiaJS and React. The problem occurs on all browsers and also on our remote Staging environment in AWS (set up by Forge).

I have tried running php artisan view:clear but this has no effect. I also tried downgrading to Horizon v5.32 but this had the same problem.

Any help appreciated

0 likes
2 replies
LaryAI's avatar
Level 58

This issue is commonly caused by a misconfiguration that results in the Horizon frontend assets (JavaScript and CSS) not being served correctly. When this happens, the browser tries to interpret an HTML error page (often a 404 or 500 error) as JavaScript, resulting in the Uncaught SyntaxError: Unexpected token '<' error.

Here are some steps to troubleshoot and resolve the issue:


1. Check Your Asset Publishing

Make sure Horizon's assets are published. Run:

php artisan horizon:publish

This will publish Horizon's assets to the public/vendor/horizon directory.


2. Check Your Web Server Configuration

Ensure your web server (Nginx/Apache/Valet) is correctly serving files from the public directory. If you are using Laravel Valet, this should work out of the box, but double-check that:

  • The public/vendor/horizon directory exists and contains JS/CSS files.
  • You can access a file like http://your-app.test/vendor/horizon/app.js directly in your browser (replace your-app.test with your local domain).

3. Clear All Caches

Sometimes, cached views or routes can cause issues. Run the following:

php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

4. Check for Route Conflicts

Since you're using InertiaJS and React, make sure you do not have a route or catch-all route (like Route::get('/{any}', ...)) that is intercepting requests to /horizon or /vendor/horizon/*. If so, you need to exclude Horizon's routes:

// Example: Exclude horizon from catch-all route
Route::get('/{any}', function () {
    // ...
})->where('any', '^(?!horizon).*$');

5. Check for Middleware Issues

Horizon registers its own routes and should not be behind authentication or other middleware that could block asset requests. If you have customized middleware in app/Providers/HorizonServiceProvider.php, revert to the default.


6. Check for .htaccess or Nginx Rules

If you have custom .htaccess or Nginx rules, ensure they are not interfering with requests to /horizon or /vendor/horizon/*.


7. Try a Fresh Install

If none of the above works, try installing Horizon in a fresh Laravel project to see if the issue persists. This can help determine if the problem is project-specific.


Summary

The most common cause is a catch-all route or asset publishing issue. Double-check that /vendor/horizon/* assets are accessible and not intercepted by your app's routes or middleware.


If you need to exclude Horizon from your React/Inertia catch-all route, here's an example:

// In your routes/web.php
Route::get('/{any}', function () {
    return Inertia::render('App');
})->where('any', '^(?!horizon).*$');

Let me know if you need more help or if you find a specific step above that resolves your issue!

nicks's avatar
nicks
OP
Best Answer
Level 3

The issue was that the following code had been added to the boot() method in AppServiceProvider. This was to facilitate displaying text originally entered in a textarea control, and ensured that line breaks in the user entry were honoured.

Blade::setEchoFormat('nl2br(e(%s))');

What it does is tell Blade to run all {{ ... }} output through e() (escape) and then nl2br(). That means every time Blade renders something, it converts newlines into <br />.

Normally, Horizon’s assets (/horizon/app.js, /horizon/vendor.js, etc.) are served through Blade templates as inline <script>...</script>. With nl2br in place, all those JS newlines become <br />, which corrupts the scripts resulting in a syntax error.

I removed this line from AppServiceProvider, which now enabled the Horizon dashboard to work correctly.

I then had to review all my code, and anywhere where a potential multi-line value was displayed replace {{ $value }} with {!! nl2br(e($value)) !!}.

Please or to participate in this conversation.