Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

fyaren's avatar

Unable to call component method. Public method [toJSON] not found on component

I have the same code on two different macos machines. On one of them I get no error, on the main mac I get this error. "Unable to call component method. Public method [toJSON] not found on component"

I've spend two days trying to figure it out. The livewire page is as follows:

    ...
</div>
 
@script
<script>

</script>
@endscript

When I Remove the @script tags, and all its contents, completely the error resolves (, but nothing works ofcourse). Even if I remove only the tag and its contents completely I still get the error.

2 likes
13 replies
LaryAI's avatar
Level 58

The error:

Unable to call component method. Public method [toJSON] not found on component

is usually caused by a JavaScript call (often via Livewire or Alpine.js) trying to invoke a method named toJSON on your Livewire component, but no such public method exists on your PHP component class.

Why does this happen?

  • Livewire tries to call a method on your component that doesn't exist.
  • Sometimes, this can be triggered by JavaScript code that tries to serialize a Livewire component or its data, or by a naming conflict.

Why does removing @script fix it?

  • The @script directive is not a standard Blade or Livewire directive. It's likely a custom directive (maybe from a package or your own macros).
  • If your @script directive is not defined or is defined differently on your two machines, it could cause Blade to render something unexpected, possibly interfering with Livewire's JavaScript.

How to fix:

  1. Check your @script directive:

    • Make sure both machines have the same Blade macros or packages installed.
    • If you use spatie/laravel-blade-javascript or similar, ensure it's installed and configured identically.
  2. Check for toJSON references:

    • Search your JavaScript for any code that might be calling .toJSON() on a Livewire component or data object.
  3. Check your Livewire component:

    • Ensure you don't have any properties or methods named toJSON that are not public.
  4. Try using standard Blade script tags:

    • Instead of @script, use the standard Blade syntax:
    <script>
        // your JS here
    </script>
    

    If this works, then the issue is with the @script directive.

  5. Synchronize your environments:

    • Run composer install and npm install on both machines to ensure dependencies are identical.
    • Clear caches:
    php artisan view:clear
    php artisan cache:clear
    php artisan config:clear
    php artisan route:clear
    

Summary:

The root cause is likely that the @script directive is not defined or behaves differently on your main Mac, causing Blade to output something that breaks Livewire's JavaScript. Either define the directive properly or use standard <script> tags.

Example fix:

Replace:

@script
<script>
    // your JS
</script>
@endscript

With:

<script>
    // your JS
</script>

Or, if you want to use the @script directive, ensure it's registered in a service provider:

Blade::directive('script', function () {
    return '<script>';
});

Blade::directive('endscript', function () {
    return '</script>';
});

Final note:
Double-check your package versions and custom Blade directives on both machines. The error is not from Livewire itself, but from a mismatch or missing directive.

Snapey's avatar

We have no idea because you shared no context or information about the error at all.

Simply saying that if I delete all my code the problem goes away, is not really of any use in helping you find the issue.

1 like
fyaren's avatar

Sorry about that. Could you be more specific about what I should share?

To clarify: I tried deleting portions of the js, but its not about my js code. Thats why I said even if I delete the tag within the @script tag I still get the error. So it's not related to my code, its related to the @script directive.

Gives Error:

<div>
...
</div>
@script
<script>[code]</script>
@endscript 

Gives Error:

<div>
...
</div>
@script
(removed all js code)
@endscript 

Doesnt give error:

<div>...</div>

1 like
Snapey's avatar

Its to do with exact error you get and its context

show the full error

1 like
fyaren's avatar

Hi Snapey,

Livewire\Exceptions\MethodNotFoundException - Internal Server Error

Unable to call component method. Public method [toJSON] not found on component

PHP 8.4.12 Laravel 12.28.1 tenant.test

Stack Trace

0 - vendor/livewire/livewire/src/Mechanisms/HandleComponents/HandleComponents.php:488 1 - vendor/livewire/livewire/src/Mechanisms/HandleComponents/HandleComponents.php:101 2 - vendor/livewire/livewire/src/LivewireManager.php:102 3 - vendor/livewire/volt/src/LivewireManager.php:35 4 - vendor/livewire/livewire/src/Mechanisms/HandleRequests/HandleRequests.php:94 5 - vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:46 6 - vendor/laravel/framework/src/Illuminate/Routing/Route.php:265 7 - vendor/laravel/framework/src/Illuminate/Routing/Route.php:211 8 - vendor/laravel/framework/src/Illuminate/Routing/Router.php:822 9 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:180 10 - vendor/laravel/boost/src/Middleware/InjectBoost.php:22 11 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 12 - vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php:50 13 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 14 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:87 15 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 16 - vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php:48 17 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 18 - vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php:120 19 - vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php:63 20 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 21 - vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php:36 22 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 23 - vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php:74 24 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 25 - vendor/stancl/tenancy/src/Middleware/IdentificationMiddleware.php:36 26 - vendor/stancl/tenancy/src/Middleware/InitializeTenancyByDomain.php:37 27 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 28 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:137 29 - vendor/laravel/framework/src/Illuminate/Routing/Router.php:821 30 - vendor/laravel/framework/src/Illuminate/Routing/Router.php:800 31 - vendor/laravel/framework/src/Illuminate/Routing/Router.php:764 32 - vendor/laravel/framework/src/Illuminate/Routing/Router.php:753 33 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:200 34 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:180 35 - vendor/livewire/livewire/src/Features/SupportDisablingBackButtonCache/DisableBackButtonCacheMiddleware.php:19 36 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 37 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php:27 38 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 39 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php:47 40 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 41 - vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php:27 42 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 43 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php:109 44 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 45 - vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php:48 46 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 47 - vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php:58 48 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 49 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php:22 50 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 51 - vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php:26 52 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:219 53 - vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:137 54 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:175 55 - vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:144 56 - vendor/laravel/framework/src/Illuminate/Foundation/Application.php:1220 57 - public/index.php:17 58 - /Applications/Herd.app/Contents/Resources/valet/server.php:167

Request

POST /livewire/update

Headers

  • cookie: remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6IlVrRUNqbTBxMG8zK3pDL1dVMk55bEE9PSIsInZhbHVlIjoidWNhREZqVStTUWFKYUxid3R5MS9hZW1ONmd2ODNBQStGY2w3NjBycmpJNnhObXM1MXNRZDdzZkx4M3hTdHBXbFg3S24vOUV3cTljYTlhS3BBdzZkbTZGQUdYTDh2S0lTN2JSdHdzTU1IR2ZuWkdtL0k3R1dHRE5WVGJiRVBtQUxTdGM3OHAwZk5ZaEV1dDUydG42Y2xIc1laWmNWbUJRNTB0WllYN2Q5ajFYaHZ6dDZlL0J6ZUp2UHE0VnRaTjUvRTJjYmd6amZJYVRhaUY3RkZmRERaYnU2Y1pVS0hGRTFqSHRTbjNFVzgxVT0iLCJtYWMiOiIwNGM0NjEyYzA5MmQ5ZDM1YzNjNjg2ZGJmMjY3YjkxZGExZTY5ZTE1ODBiOTZmZDVkODU0YWI5ODk0YmRmOGM5IiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IkxXRVhWaDMzalB1V2lFbXdZVzZsY2c9PSIsInZhbHVlIjoiRTJrMGw2R0RWVEkzSGx0eXNNRVprNUw3R0Q3bTNhVFlMbXk1YWR1SkRkSFBIc0JIajQ3MVZrTS9oMU5kZHRYTmU2OWdSMExncXpCSzB1S0FHZ2lyT3BmSGF0TTlreDNSTEFXQ201ZG12bjI2Y0dYKzByN1lzOTFjaFpnQ0FsTXoiLCJtYWMiOiJlZjE3ZDIxODljMGFkMjMyYjgwNDNkMGJiNzM4ZmYwNTliMWQxMGU4MmU3ZmI3ZjkwNGVmYzI4ZTY1NzY0ZWRhIiwidGFnIjoiIn0%3D; itaks_session=eyJpdiI6IlJOcVIzbVdnMEQ1amtLQnV5REJLb2c9PSIsInZhbHVlIjoiL21oN0h2bEFsTE5FY29USlFaNFlKb3hURWpwMmtJM0VmUmYrSnB0NTBYN3pkQi9mUm90NzFWT2NkWEJJNkp5WTZpWkw0YWhnZlBPZ04vYk9vRllRSWdudkZGWmNvamxFY3pWVzZDS0lVNTJ4bjBlajNlOHFOdTdYeHBkcXg4S0ciLCJtYWMiOiI0YTAyMGViYjliYmVjNjFkY2ZkMmVhZmY2MDI2YWQyNWE4MTljODkxZDg3MTI1ZmY5NTQ2MTcyZDM3YTEyNmE2IiwidGFnIjoiIn0%3D
  • priority: u=1, i
  • accept-language: en-US,en;q=0.9,ru;q=0.8
  • accept-encoding: gzip, deflate, br, zstd
  • referer: https://tenant.test/
  • sec-fetch-dest: empty
  • sec-fetch-mode: cors
  • sec-fetch-site: same-origin
  • origin: https://tenant.test
  • accept: /
  • sec-ch-ua-mobile: ?0
  • x-livewire:
  • content-type: application/json
  • dnt: 1
  • sec-ch-ua: "Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"
  • user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36
  • sec-ch-ua-platform: "macOS"
  • cache-control: no-cache
  • pragma: no-cache
  • content-length: 4995
  • host: tenant.test

Route Context

controller: Livewire\Mechanisms\HandleRequests\HandleRequests@handleUpdate route name: livewire.update middleware: web, universal, Stancl\Tenancy\Middleware\InitializeTenancyByDomain

Route Parameters

No route parameter data available.

Database Queries

  • sqlite - select * from "tenants" where exists (select * from "domains" where "tenants"."id" = "domains"."tenant_id" and "domain" = 'tenant.test') limit 1 (0.26 ms)
  • sqlite - select * from "domains" where "domains"."tenant_id" in ('tenant') (0.06 ms)
  • tenant - select * from "sessions" where "id" = 'FFajuFofpYjd8INpQwpEm9X0ndGUCiXSwHwGjIMi' limit 1 (0.36 ms)
  • tenant - select * from "users" where "id" = 1 limit 1 (0.43 ms)
fyaren's avatar

Found the culprit.

I have this code:


                            @if (in_array('popular', tenant('settings')['address_sources']) && !empty(tenant('settings')['popular_addresses']))
                            // Popular addresses
                            {
                                sourceId: 'popularAddresses',
                                getItems() {
                                    return [
                                        @foreach ( explode("\n", tenant('settings')['popular_addresses']) as $address )
                                            // IF first item of loop, display dummy. Because the very first item of the very first loopitem doesnt display weirdly.
                                            @if($loop->first) {text: 'dummy', id: 'dummy', hidden: true}, @endif

                                            {text: '{{ $address }}', id: '{{ $address }}',},
                                        @endforeach
                                    ];
                                },
                                templates: {
                                    header({html}) { return html`<b>Populaire adressen</b>`; },
                                    item({ item, components, html }) {
                                        return html`<div>${item.text}</div>`;
                                    }
                                },
                                onSelect({ item, setQuery, event }) {
                                    setQuery(item.text);
                                    wireSetWaypoint(elementId, item.text);
                                    event.preventDefault();
                                }
                            },
                            @endif 

The @foreach loop leaves a mark in the compiled js I think. Whenever the first if is false it should ignore the whole block. But that doesnt happen. This error is there when the popular addresses is empty. When I have 1 or more addresses in that array, the error disappears.

I didnt deep dive into it i still dont know why for example when I delete the tag and all its contents, i still get the error. Because outside of this block there is no reference to or usage of the populare_addresses var.

Now at least I know where to look further.

Snapey's avatar

I've been doing this stuff for over 10 years, And I cant get my head around this code. It looks like you are trying to use blade to compile json.

Whatever it is you are doing, its incomprehensible and certainly not best practice. Probably leading to errors like "doesn't display, wierdly"

jlrdw's avatar

I suggest the 30 days to learn laravel course and the Livewire 3 From Scratch course.

Both are free right here.

fyaren's avatar

I use autocompletejs in a livewire component and have conditional data sources. With php you could check if certain sources exist and echo the js or completely omit it. With blade the @if/@foreach directives leave a trace I think.

What I have experienced before was that; livewire components, when used enough/too much/too complex? custom js, has some trouble sending it over the line. And will give unpredictable errors.

Please or to participate in this conversation.