Skip to content

Using Blaze with Laravel Folio page + Livewire Volt embedded in the page causing corrupt component payload exception on interaction with Volt's props / method #187

Description

@mulky-sulaiman

Describe the bug
Using laravel folio page routes with embedded livewire volt in it causing livewire to throw exception of corrupt component payload on interaction with livewire props / method

I suspect this happened because blaze see the inline anonymous volt component (automatically named as volt-anonymous-fragment-*) to be a regular anonymous component and automatically optimize it, thus making livewire sees the mismatch and throw the corrupt component payload exception.

-Been tried to set Blaze to only do the optimization to the specific directory and/or exclude path for Folio's page also not helps.
-Wrapping the volt directive, or the whole folio page, with @unblaze/@endunblaze causing the volt/folio page not being rendered any at all.
-Workaround attempt to add middleware in folio pages to disable blaze manually also not work, since it came too late that the folio page already been optimized before the middleware run.

Only workaround is to completely disable blaze at app level (config / env). Once it is disabled, all works fine as it is supposed to.

My question is there any way to skip the compilation for volt-anonymous-fragment-* component, or to exclude that for being optimized by blaze ?

Component causing the issue

{{-- pages/test.blade.php --}}
@props(['title' => 'Test'])
<?php
use Illuminate\Http\Request;
use Illuminate\View\View;
use Livewire\Attributes\On;
use Livewire\Volt\Component;

use function Laravel\Folio\middleware;
use function Laravel\Folio\name;
use function Laravel\Folio\render;

// Volt
new class extends Component
{
    public $count = 0;

    #[On('increment')]
    public function increment(): void
    {
        $this->count++;
    }

    #[On('decrement')]
    public function decrement(): void
    {
        if ($this->count <= 0) {
            return;
        }
        $this->count--;
    }
};

// Folio
render(function (Request $request, View $view): View {
    $message = __('Hello from Folio');

    return $view->with(compact('message'));
});

name('test');
middleware([]);
?>
<x-layouts::root :$title>
    <div x-data="testData">
        @volt('test')
            <div>
                <div class="flex items-center gap-2">
                    <button x-on:click.prevent="$wire.decrement">-</button>
                    <h1>{{ $count }}</h1>
                    <button x-on:click.prevent="$wire.increment">+</button>
                </div>
            </div>
        @endvolt
        <div>
            <template x-if="message">
                <div>Hello, <span x-text="message"></span></div>
            </template>
            <button x-on:click.prevent="callByAxios()" x-bind:disabled="processingAxios">Call Api using
                Axios</button>
            <button x-on:click.prevent="callByFetch()" x-bind:disabled="processingFetch">Call Api
                using
                Fetch</button>
        </div>
        <div>{{ $message }}</div>
        @push('scripts')
            <!-- Test Page -->
            <script defer type="text/javascript">
                document.addEventListener("alpine:init", () => {
                    Alpine.data("testData", () => ({
                        message: '',
                        processingAxios: false,
                        processingFetch: false,
                        async callByAxios() {
                            this.processingAxios = true;
                            const response = await api.get('api/test');
                            setTimeout(() => {
                                this.processingAxios = false;
                                this.message = response?.data.message + '(Axios)';
                            }, 2000);
                        },
                        async callByFetch() {
                            this.processingFetch = true;
                            const response = await $fetch.get('/api/test');
                            setTimeout(() => {
                                this.processingFetch = false;
                                this.message = response?.message + '(Fetch)';
                            }, 2000);
                        }
                    }))
                });
            </script>
        @endpush
    </div>
</x-layouts::root>

Expected behavior
Clicking - or + button works by calling correct volt's method

Actual behavior
Livewire throws exception of

Livewire\Mechanisms\HandleComponents\CorruptComponentPayloadException
vendor/livewire/livewire/src/Mechanisms/HandleComponents/Checksum.php:30
Livewire encountered corrupt data when trying to hydrate a component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.

Environment

  • Laravel version: 13.17.0
  • PHP version: 8.5.5
  • Blaze version: 1.0.12
  • Livewire version : 4.3.3
  • Volt version : 1.10.5

Additional context
Completely disable blaze at app level (config / env) fixes the issue.

Activity

  1. changed the title [-]Using Blaze with Laravel Folio page + Livewire Volt embedded in the page page causing corrupt component payload exception on interaction with Volt's props / method[/-] [+]Using Blaze with Laravel Folio page + Livewire Volt embedded in the page causing corrupt component payload exception on interaction with Volt's props / method[/+] on Jun 29, 2026
  2. calebporzio commented on Jul 4, 2026

    @calebporzio
    Contributor

    Thanks for the detailed report — this one was a fun hunt, and your instinct was close.

    It wasn't Blaze optimizing the volt-anonymous-fragment-* component itself. Volt compiles @volt fragments into a Livewire mount that captures the whole surrounding template scope via get_defined_vars(), filtering out the framework variables it knows about. Blaze introduces variables Volt doesn't know about ($__blaze plus a couple of call-site temporaries from your layout component), so they got forwarded to Livewire, stored in the snapshot, and broke the checksum on the next request. That's also why directory scoping and @unblaze couldn't save you — $__blaze is injected into every view while Blaze is enabled.

    I reproduced your exact setup (Folio page + embedded @volt counter inside a layout component, Laravel 13 / Livewire 4.3.3 / Volt 1.10.5) and got the same CorruptComponentPayloadException — fix is up in #188. With it applied, interactions work and the snapshot matches what you get with Blaze disabled. Once it's merged and tagged you can drop the workaround and re-enable Blaze.

  3. mulky-sulaiman commented on Jul 4, 2026

    @mulky-sulaiman
    Author

    that is great, thank's a lot @calebporzio ! looking forward for the PR release

  4. ganyicz commented on Jul 27, 2026

    @ganyicz
    Collaborator

    I double-checked this and while the analysis is correct — the get_defined_vars() captures the $__blaze variable which causes the checksum error — I believe the exclusion should be done from inside Volt.

    The original PR achieves this by adding a new method to Blaze to exclude variables with __blaze prefix, those that match the following regex: '/^__(?:attrs|slots)(?:Stack)?[0-9a-f]{32}$/' and adds a new compiler pass to rewrite the compiled Volt code.

    Simply adding __blaze to the exclusion list inside ExtractFragments::componentArguments() fixes the issue.

    We do not need the complex exclusion rules because there are no other variables with __blaze prefix and while the attrs/slots variables will still be captured by get_defined_vars(), this matches the default Volt functionality even without Blaze.

    I have submitted a PR to Volt: livewire/volt#156

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions