Livewire: Livewire encountered corrupt data when trying to hydrate the component issue.

Created on 8 Nov 2019  ยท  63Comments  ยท  Source: livewire/livewire

Describe the bug
Short: I have an array of tasks, just a 2d array with text in keys, that livewire is loosing state on.

Longer: This is a volunteer school board project that I'm going VERY YANGI on, in the hopes it takes just a few days of spare time. We have a bunch of shared tasks, that I'm putting online for the right people to see.

I made a simple checklist component and added it to the site, I haven't even put items in a DB at this point, (perhaps that could help, but I decided to go all the way for the YAGNI)

Here is the component model, I"m just putting the whole thing in as is so it's easy to test:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Checklist extends Component
{
    public $flash = '';
    public $question = '';
    public $tasks = [
        'setup_the_system'=>[
            'title_note' => 'Most of this section is stuff that you won\'t readily be able to see,
            for example programming this checklist and the ability to ask questions here. However,
            it\'s all very helpful in moving this forward in the easiest way possible to solve problems
            in the easiest ways we can think of.',
            'create_visual_checklist_format' => 1,
            'create_version_repository'=>1,
            'create_version_repository_note'=> 'This basically will show all versions of the project, it\'s a <em>DR</em>
            (Disaster recovery) mechanism, in case I kick the bucket, another person can take over with a list of everything
            that\'s ever been done and things that need to get done in order to move forward. I will also endeavour to
            find someone to take over for me in case that should occur.',
            'kick_bucket_replacement_volunteer_found' => 0,
            'put_up_temporary_site'=>1,
            'put_up_temporary_site_note'=>'you are on it, the data on here will constantly be destroyed and re-written
            as we get ready to make something real! As real as this feels, don\'t save anything here that is important.
            Instead email me or keep a word doc, or basically anything else other than saving real data here.',
        ],
        'PAC USE CASES (A CHECK MEANS IT\'S AGREED UPON)' => [
            'Gatekeeper authorizes guardians who register'=>1,
            'Gatekeeper authorizes guardians who register_note'=> 'The <b>"Gatekeeper"</b> is a PAC member who has access
             to information and knows which families are attending the school and which ones are not.<br><br>
             Anyone who registers need to go through a 2 step process to have access to <b><em>any</em></b> information.
             Step 1 is simply verifying their email address which they can do without any intervention from the gatekeeper.
             Step 2 requires a person to actually allow the verified guardian access to see our internal information.
             Step 2 will also need to be re-done every year.',
            'Gatekeeper is notified each time someone registers'=>1,
            'Gatekeeper is notified each time a child is registered'=>1,
            'Gatekeeper confirms child details including homeroom'=>1,
            'Gatekeeper confirms child details including homeroom_note'=> '
            This seems overwhelming for 1 person, it could even be 2 people sitting together on skype or in an office
            calling out names, it should take more than an evening or 2.
            ',

            'pac members / room reps can send notifications to their classes'=>0,
            'pac members / room reps can send notifications to their classes_note'=>'
            This is an idea, notice the unchecked box, and opinions are welcome. <br><br>
            Instead of a cumbersome trickle down human information system PAC emails me, I email my room constituents,
            perhaps school wide updates like the PAC meeting details can just be summarized and sent to the people who
            want notification. Either everyone if it\'s deemed important or, people who subscribed to news in some fashion.<br><br>
            When there are room specific issues, we could then pass those on directly as room reps.
            ',
        ],

        'GUARDIAN USE CASES (A CHECK MEANS IT\'S AGREED UPON)' => [
            'Guardian can register their children'=>1,
            'Guardian can add other guardians to their family' => 1,
            'Guardian can add other guardians to their family_note' => '
            Guardians who are added get a notification email to register',
            'Should invited guardians need to be confirmed by gatekeeper?'=>0,
            'Should invited guardians need to be confirmed by gatekeeper?_note'=>'
            For example, I go through registration and get confirmed. I then add another guardian Jane, and
            Jane gets an email to register. Jane registers and gets verified via email.<br><br>
            Does she need to get confirmed too?',
            'Guardians add children'=>1,
        ]
    ];

    public function render()
    {
        return view('livewire.checklist');
    }


    public function askMe()
    {
        $this->flash = $this->question;
        $this->question = '';
    }
}
<div class="">
    @if(!empty($flash))
        <div class="p-12 bg-blue-100">{{$flash}}</div>
    @endif

    <div class="flex flex-col md:flex-row">
        <div class="w-full md:w-1/2">
            @foreach($tasks as $title => $group)
                <div
                    class="font-semibold mt-4 tracking-wide text-sm uppercase text-gray-600">{{ str_replace('_',' ',$title) }}</div>
                @foreach($group as $key=>$value)
                    @if(is_array($value))
                        <div
                            class="font-semibold mt-4 ml-8 tracking-wide text-sm uppercase text-gray-600">{{ str_replace('_',' ',$key) }}</div>
                        @foreach($value as $childKey=>$childValue)
                            @if(Str::endsWith($childKey,'_note'))
                                <div
                                    class="mt-1 ml-12 pl-3 tracking-wide text-sm text-gray-600">{!! $childValue !!}</div>
                            @else
                                <label class="ml-8 flex items-center mt-2">
                                    <input type="checkbox"
                                           wire:model.lazy="tasks.{{ $title }}.{{ $key }}.{{ $childKey }}"
                                           class="form-checkbox" @selected($tasks[$title][$key][$childKey],1)>
                                    <span class="ml-2">{{ str_replace('_',' ',$childKey) }}</span>
                                </label>
                            @endif
                        @endforeach
                    @else
                        @if(Str::endsWith($key,'_note'))
                            <div
                                class="mt-1 {{ ($key != 'title_note'? 'ml-4 pl-3': '') }} tracking-wide text-sm text-gray-600">{!! $value !!}</div>
                        @else
                            <label class="flex items-center mt-2">
                                <input type="checkbox" wire:model.lazy="tasks.{{ $title }}.{{ $key }}"
                                       class="form-checkbox" @selected($tasks[$title][$key],1)>
                                <span class="ml-2">{{ str_replace('_',' ',$key) }}</span>
                            </label>
                        @endif
                    @endif
                @endforeach
            @endforeach


        </div>
        <div class="w-full md:w-1/2 mt-4">
            <div class="md:fixed md:w-5/12">
                <div class="flex flex-col w-full md:ml-12">
                    <div class="font-semibold tracking-wide text-sm uppercase text-gray-600">Questions / Concerns</div>

                    <label class="block mt-2 w-full mx-auto">
                        <div class="form-label">I'd like to know ... @error('question')<br>{{ $message }}@enderror</div>
                        <textarea wire:model.lazy="question" name="question" id="question" autocomplete=""
                                  autocapitalize="off"
                                  rows="15"
                                  class="form-input block w-full @error('question') error @enderror"
                                  placeholder="how can I help you?">{{ $question }}</textarea>
                    </label>

                    <button wire:click.prevent="askMe" class="btn brand w-full mt-6">Ask Me Stuff!</button>
                </div>
            </div>
        </div>
    </div>
</div>

It produces something like this:
Screen Shot 2019-11-08 at 1 48 11 PM

To Reproduce
Steps to reproduce the behavior:

  1. Make a livewire enabled project
  2. Add the checklist component
  3. Add any input to the Ask Me a Question Field
  4. Click the button

Expected behavior
The flash public item will get the data from the text area

Screenshots
If applicable, add screenshots to help explain your problem.
Screen Shot 2019-11-08 at 1 51 29 PM

Desktop (please complete the following information):
Macos Catalina Brave browser, same thing happens in google chrome.

Additional context
When I shrink the array down it will work or fail at some random size.

There is no way here to "key" this up without a re-implementation maybe numeric keys or task objects. But it feels unnecessary for something so small and simple.

Most helpful comment

Great tips, thanks @lucasromanojf !

All 63 comments

Screen Shot 2019-11-09 at 10 31 59 PM

Can you use some sort of unique-key implementation when making an array element?

Could you further elaborate why you believe this is related to unique-keys? I have the same problem in a form.

Hi, I was able to reproduce the problem where the hashes start to differ:

This option gives the same hash

public $tasks = [
    'test' => [
        'test' =>
            'notspace',
    ],
];

But if you put a space, then the hashes will no longer match:

public $tasks = [
    'test' => [
        'test' =>
            ' space',
    ],
];

Most likely we do trim when forming, but we do not use it for comparison.
Because if you change its generation to:

<?php

namespace Livewire;

class ComponentChecksumManager
{
    public function generate($name, $id, $data)
    {
        $hashKey = app('encrypter')->getKey();

        $data = array_walk_recursive($data, 'trim'); //Added line

        $stringForHashing = $name . $id . json_encode($data);

        return hash_hmac('sha256', $stringForHashing, $hashKey);
    }

    public function check($checksum, $name, $id, $data)
    {
        return hash_equals($this->generate($name, $id, $data), $checksum);
    }
}

Hashes will match again. We found a reason, but this is definitely not a good solution.

I think it's worth waiting for @calebporzio and getting his opinion.

@roni-estein, I pulled down your "checklist" component and it seemed to work how it should:
Nov-11-2019 11-23-20

@tabuna, thanks for boiling the issue down further. I tried the tasks data you posted and it worked fine as well.

Is that data breaking for you both? (the data with the space in it)

I'm guessing this is related to the following feature of Livewire:

  • By default Laravel adds a "TrimStrings" middleware to requests that would normally cause breakages like this.
  • Livewire has some code in the Service Provider (will post after) that bypasses this middleware for Livewire requests so there aren't data mismatches like this.
  • It's possible for some reason that this bypassing isn't happening in your projects. In which case, we should investigate why.

(the bypassing middleware bit from: src/LivewireServiceProvider.php):

        if ($this->app['livewire']->isLivewireRequest()) {
            $this->bypassMiddleware([
                TrimStrings::class,
                ConvertEmptyStringsToNull::class,
            ]);
        }

Thanks for submitting a thorough issue, and thanks everyone else for pitching in. Insanely helpful, really.

Also, shouldn't have anything to do with unique keys @roni-estein & @cihantas

If you are having issues @cihantas, pull down the latest version of Livewire. If that doesn't fix it, open an issue.

Also, key= is a typo in the docs, it should be wire:key= - I'll fix that stat.

Thanks!

Guys thanks so much for checking it out, so busy with kids and "play dates" for them that I haven't sat down at a screen until now. I'll update livewire and try to clear some caches. I did want to bring up, that this project has insane potential and with maintainers who are so quick to solve issues and help point out our "own" errors, it's a pleasure to work on.

I really appreciate it.

Ok, I've tried hammering through this a couple of ways, and I published a sample new project with nothing in it except this component. https://github.com/roni-estein/test Please take a quick look and see if we can find the difference in your working version and mine. Sorry I forgot to meniton I still have the same error.

Ok, adding this to AppServiceProvider works ObjectPrybar needs to be imported. However shouldn't that already be loaded by LivewireServiceProvider?

/**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if ($this->app['livewire']->isLivewireRequest()) {
            $this->bypassMiddleware([
                TrimStrings::class,
                ConvertEmptyStringsToNull::class,
            ]);
        }
    }

    protected function bypassMiddleware(array $middlewareToExclude)
    {
        $kernel = $this->app->make(\Illuminate\Contracts\Http\Kernel::class);

        $openKernel = new ObjectPrybar($kernel);

        $middleware = $openKernel->getProperty('middleware');

        $openKernel->setProperty('middleware', array_diff($middleware, $middlewareToExclude));
    }

Ok, the problem is that Livewire only ignores the vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php middleware, not the local app one (app/Http/Middleware/TrimStrings.php).

I added both now to the bypass.

This fix will be out in the next release.

Thanks for uploading that repo @roni-estein - big help!

not opening a new issue for this,

right now, dev master is generating this, I'll switch back to 3.21 for now, but just incase this was an unintended issue

Screen Shot 2019-11-12 at 3 01 09 PM

Thanks for the report @roni-estein, I fixed this and pushed the fix to dev-master. I think it's actually a bug from Laravel 6. (I upgraded the project's testing suite to 6 just now). I'll look into PRing a fix to Laravel.

It's caused by using the @error directive (that I actually PR'd to Laravel lol). Should work now though.

Nice!

Hello everyone... just curious if anyone else is having this issue with v0.5.3 of livewire and laravel v6.9.0

Every time I try to trigger an event, or update some data in a livewire component from the front of my application I get the error that started this thread...

Livewire\Exceptions\CorruptComponentPayloadException
Livewire encountered corrupt data when trying to hydrate the [my-super-secret-component] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.

It doesn't happen on initial page load, but I've ran into it when I trigger a wire:click or try to bind data to an input.

What I don't understand is everything was working fine, and I can't seem to figure out at what point I went from "all is working" to "something is broken"

Any help would be appreciated! :)

Thanks!

Hello everyone... just curious if anyone else is having this issue with v0.5.3 of livewire and laravel v6.9.0

Every time I try to trigger an event, or update some data in a livewire component from the front of my application I get the error that started this thread...

Livewire\Exceptions\CorruptComponentPayloadException
Livewire encountered corrupt data when trying to hydrate the [my-super-secret-component] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.

It doesn't happen on initial page load, but I've ran into it when I trigger a wire:click or try to bind data to an input.

What I don't understand is everything was working fine, and I can't seem to figure out at what point I went from "all is working" to "something is broken"

Any help would be appreciated! :)

Thanks!

I am having the same issue :(
It looks like it happens for me when I have public properties other than string (boolean, for example).

It happened to me if I set the public $id to another value in the mount() method. I used $id to keep track of a model-id, but I didn't know the component id was stored in that variable.
Failing code:
public function mount($model_id) { $this->id = $id; // Not good to override this dude }

The reason it failes, is that the ComponentChecksumManager uses the id when comparing checksums.

Just a quick update on this...

I set up a new project the other day (Livewire 0.6.0 & Laravel 6.11.0) and haven't had this issue at all. So I went back to the project I initially had this problem with and updated to Livewire 0.6.0 & Laravel 6.11.0, but am still getting the same error when trying to toggle a boolean property.

Livewire encountered corrupt data when trying to hydrate the [recent-posts] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.

I'm not overriding/setting name, id or data on any of my Livewire components, in fact I've removed all components but one, and that component only has one function which toggles a public property, a boolean. When triggering that function via wire:click I continue to get the error above.

Is there anything I can do to get around this? If I understood better what was going on and how to fix it I'd be happy to help with a pull request. :)

Thanks!

Hi @EldonYoder, You'll have to post some source code for us to help you with that. Ideally something we can run simply on our own machines.

Hmmm @lucasmichot - I can set boolean properties fine. I'm wondering if any of this is because of a specific middleware setup you have in your Laravel app. That's maybe why we can't replicate this in a fresh Laravel install.

@calebporzio - Ooops... duh I should have given some source code... ๐Ÿคฆโ€โ™‚๏ธ

The app is a pretty simple "weight tracking" tool and this is the RecentWeights Component.

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class RecentWeights extends Component {
    public $recent_weigh_ins;
    public $display_weigh_ins = false;

    public function mount() {
        $this->recent_weigh_ins = auth()->user()->weigh_ins->sortByDesc( 'when' );
    }


    public function render() {
        return view( 'livewire.recent-weights' );
    }

    public function toggle_weigh_ins() {
        $this->display_weigh_ins = ! $this->display_weigh_ins;
    }
}

Here is the corresponding Livewire blade template.

<div class="max-w-2xl">
    @if( count($recent_weigh_ins) > 0 && $display_weigh_ins )
        <h3 class="mt-12 font-bold text-gray-900">Recent Weigh Ins (yeah, I know these aren't pretty right now.)</h3>
        <ul class="mt-3 list-inside list-disc">
            @foreach ($recent_weigh_ins as $weigh_in)
                <li class="mt-2">
                    {{ $weigh_in->weight }} | {{ $weigh_in->when->format('Y.m.d') }}
                </li>
            @endforeach
        </ul>
    @endif

    @if( count($recent_weigh_ins) > 0 && ! $display_weigh_ins )
        <button class="form-input mt-4 bg-blue-1000 hover:bg-blue-800 text-gray-100 mt-2" wire:click="toggle_weigh_ins">Show Recent Weigh Ins</button>
    @endif
</div>

I'd be more than happy if this was just me doing something dumb and not realizing it... :)

Not sure why you've mentioned me @calebporzio?
Nevertheless, I hope you're doing fine ?!

Great to see livewire and alpine projects sky-rocket!
Take care mate ๐Ÿ™

Ha, oops! Meant the other Lucas lol. Thanks bud!

I did the same thing Caleb in another issue ๐Ÿ˜…

Just to bump this issue, I'm getting the exact same error as @EldonYoder, under the same circumstances. I have a nested component that I'm @foreach-ing over.

The error is:

Livewire encountered corrupt data when trying to hydrate the [student-list-item] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests. 

I've pulled out basically all of the logic, and just clicking the button in the nested component throws that error. Here are the parent and child components:

ListStudents.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Adldap\Laravel\Facades\Adldap;
use App\User;

class ListStudents extends Component
{
    protected $listeners = ['updateStudents' => 'getStudents'];

    public function getStudents()
    {
        return User::students()->get()->sortBy('last_name');
    }

    public function render()
    {
        $students = $this->getStudents();

        return view('livewire.list-students', ['students' => $students]);
    }
}

_User::students() is a scope on the User model:_

    public function scopeStudents($query)
    {
        return $query->where('title', 'Student');
    }

list-students.blade.php

<div>
    <div class="overflow-x-auto bg-white rounded shadow bg-blue-050">
        @foreach ($students as $student)
        @livewire('student-list-item', $student, key($student->id))
        @endforeach
    </div>
</div>

StudentListItem.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class StudentListItem extends Component
{
    public $firstName;
    public $lastName;
    public $email;
    public $ea1;
    public $show = false;
    public $id;

    public function toggleShow()
    {
        //
    }

    public function mount($student)
    {
        $this->firstName = $student->first_name;
        $this->lastName = $student->last_name;
        $this->email = $student->email;
        $this->id = $student->id;

    }
    public function render()
    {
        return view('livewire.student-list-item');
    }
}

student-list-item.blade.php

<div>
    <button class="block w-1/4 text-gray-500" wire:click="toggleShow">
        Show</button>
</div>

Like I said, I had other logic and stuff in there, but pulled it out as I was trying to debug. The Ignition trace doesn't seem to show any middleware in the way.

Using Livewire 0.7.0, with Laravel 6.11.0, and Valet with PHP 7.3.

OK, I got it, but I don't know why.

I replaced this:

public function mount($student)
    {
        $this->firstName = $student->first_name;
        $this->lastName = $student->last_name;
        $this->email = $student->email;
        $this->id = $student->id;

    }

with this:

public $student;

public function mount($student)
    {
        $this->student = $student;
    }

and changed the corresponding Blade files, and it worked.

@skoontastic The reason it didn't work was because you override the $id of the component. You should not use $this->id = $student->id;.
$id is used by the ComponentChecksumManager uses the id when comparing checksums.
If you used $this->studentid = $student->id; it would have worked (I think)

Hey everyone,

I finally narrowed my issue down to one of my public properties... I switched from this...

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class RecentWeights extends Component {
    public $recent_weigh_ins;
    public $display_weigh_ins = false;

    public function mount() {
        $this->recent_weigh_ins = auth()->user()->weigh_ins->sortByDesc( 'when' );
    }


    public function render() {
        return view( 'livewire.recent-weights' );
    }

    public function toggle_weigh_ins() {
        $this->display_weigh_ins = ! $this->display_weigh_ins;
    }
}

to this...

<?php

namespace App\Http\Livewire;

use App\WeighIn;
use Livewire\Component;

class RecentWeights extends Component {

    public $recent_weigh_ins;
    public $display_weigh_ins;
    public $user_id;

    public function mount() {
        $this->user_id           = auth()->user()->id;
        $this->recent_weigh_ins  = WeighIn::where( 'user_id', $this->user_id )
                                                ->orderBy( 'when', 'asc' )
                                                ->get();
        $this->display_weigh_ins = false;
    }


    public function render() {
        return view( 'livewire.recent-weights' );
    }

    public function toggle_weigh_ins() {
        $this->display_weigh_ins = ! $this->display_weigh_ins;
    }
}

...and that fixed my hydration issue...

Again, I'm not entirely sure why. The first method seemed fine until I added any interactivity to it.

Hope thats helpful to someone!

@skoontastic The reason it didn't work was because you override the $id of the component. You should not use $this->id = $student->id;.
$id is used by the ComponentChecksumManager uses the id when comparing checksums.
If you used $this->studentid = $student->id; it would have worked (I think)

Thanks for the tip! Makes sense. Didn't know that was a thing.

I got this issue when using public $createUrl; and assigning a URL to it in the mount() method. Not sure what may be causing this. The url is the following: "//localhost:3000/localities/create".

@mikebronner - I couldn't replicate the issue:
image

Worked fine for me. We'll need something more to debug.

I'll try to get a failing test repo set up. :)

I was able to fix my issue. The issue was that I had a middleware that was responsible for sanitizing request inputs to avoid XSS attacks. Removing this middleware (that is not needed for me anymore but was years ago) fixed the issue. Probably you guys that are having this same issue do not have this middleware like me, so I suggest checking if there is something somehow changing your request input before reaching the Livewire component.

I was able to fix my issue. The issue was that I had a middleware that was responsible for sanitizing request inputs to avoid XSS attacks. Removing this middleware (that is not needed for me anymore but was years ago) fixed the issue. Probably you guys that are having this same issue do not have this middleware like me, so I suggest checking if there is something somehow changing your request input before reaching the Livewire component.

Being more specific, this code was making the issue happen with non-string public properties:

private function arrayStripTags($array)
{
        $result = [];

        foreach ($array as $key => $value) {
            // Don't allow tags on key either, maybe useful for dynamic forms.
            $key = strip_tags($key);

            // If the value is an array, we will just recurse back into the
            // function to keep stripping the tags out of the array,
            // otherwise we will set the stripped value.
            if (is_array($value)) {
                $result[$key] = $this->arrayStripTags($value);
            } else {
                // I am using strip_tags(), you may use htmlentities(),
                // also I am doing trim() here, you may remove it, if you wish.
                $result[$key] = trim(strip_tags($value));
            }
        }

        return $result;
}

private function globalXssClean()
{
        // Recursive cleaning for array [] inputs, not just strings.
        $sanitized = $this->arrayStripTags(Request::all());
        Request::merge($sanitized);
}

public function handle($request, Closure $next)
{
        //XSS protection
        $this->globalXssClean();

        return $next($request);
}

I was able to fix my issue. The issue was that I had a middleware that was responsible for sanitizing request inputs to avoid XSS attacks. Removing this middleware (that is not needed for me anymore but was years ago) fixed the issue. Probably you guys that are having this same issue do not have this middleware like me, so I suggest checking if there is something somehow changing your request input before reaching the Livewire component.

Being more specific, this code was making the issue happen with non-string public properties:

private function arrayStripTags($array)
{
        $result = [];

        foreach ($array as $key => $value) {
            // Don't allow tags on key either, maybe useful for dynamic forms.
            $key = strip_tags($key);

            // If the value is an array, we will just recurse back into the
            // function to keep stripping the tags out of the array,
            // otherwise we will set the stripped value.
            if (is_array($value)) {
                $result[$key] = $this->arrayStripTags($value);
            } else {
                // I am using strip_tags(), you may use htmlentities(),
                // also I am doing trim() here, you may remove it, if you wish.
                $result[$key] = trim(strip_tags($value));
            }
        }

        return $result;
}

private function globalXssClean()
{
        // Recursive cleaning for array [] inputs, not just strings.
        $sanitized = $this->arrayStripTags(Request::all());
        Request::merge($sanitized);
}

public function handle($request, Closure $next)
{
        //XSS protection
        $this->globalXssClean();

        return $next($request);
}

Here is a tip:

1) On your last Laravel middleware, before the request reaches Livewire, add a "dd($request->all())".
2) Then, check if the request inputs in your "dd" are somehow different from what you see on Chrome devtools.

In my case, the code I mentioned before was changing the boolean property value from "true" to "1" and an integer property value from 1 (int) to "1" (string) before reaching Livewire. This is why I was having this error for every public non-string property.

Great tips, thanks @lucasromanojf !

Great tips, thanks @lucasromanojf !

@calebporzio, I refuse to take any credit for @lucasromanojf 's tip! Even if, indeed, it's a good one ๐Ÿ‘

@calebporzio you're always welcome but I am not @lucasmichot hahahaha

Lol, for some reason his name shows up first for autocomplete even if he's not in this issue. I changed it like a second later, surprised he still got the notification. Ugh... Carry on Lucases

Lol, for some reason his name shows up first for autocomplete even if he's not in this issue. I changed it like a second later, surprised he still got the notification. Ugh... Carry on Lucases

Haha no problem :D

I think this is not related to pr i just made, But similar problems i have a detailed explanation on pr you can check it out, i might help.

This still occurs as @lalov mentioned. Maybe the $id public property should be renamed to something more component oriented such as public $componentId?

This was the first thing I ran into getting out of the gate when creating a component for a form. I added a public $id property to store the ID of a model that is being updated.

If it was renamed it would be much harder to run into this issue.

@stevebauman, the next release of Livewire (v1.0.2 probably) will now throw an exception if you try to set public $id in your component.

I'm closing this for now.

Re-open if someone encounters an issue that hasn't been already addressed in this thread.

This error can be thrown for a number of different reasons, so I imagine new cases will crop up. Thanks!

@stevebauman, the next release of Livewire (v1.0.2 probably) will now throw an exception if you try to set public $id in your component.

Perfect - works for me! Thanks Caleb ๐Ÿ‘

@skoontastic The reason it didn't work was because you override the $id of the component. You should not use $this->id = $student->id;.
$id is used by the ComponentChecksumManager uses the id when comparing checksums.
If you used $this->studentid = $student->id; it would have worked (I think)

This saved me alot

Hello friends! Sorry for write over closed issue, however I found a "rare behavior"..., I have a simple LiveWire component for a pair of dependent selects..., all work fine and later, after a bit of clicks, the component fail with a "CorruptComponentPayloadException" error.

https://youtu.be/t3lj7GRB9TI

Any idea about this??

@smockermaster do you have any custom middleware interacting with input data?

Hi @stevebauman , no, I just use StateCity LiveWire component and the view...

`
class StateCity extends Component
{
public $state_id;
public $city_id;
public $cities = [];

public function mount ($state_id, $city_id){
    $state_id == 0 ? $this->state_id = '' : $this->state_id = $state_id;
    $city_id == 0 ? $this->city_id = '' : $this->city_id = $city_id;
}

public function render()
{
    if(!empty($this->state_id)){
        $this->cities = City::where(['state_id' => $this->state_id])->get()->sortBy('city');
    }
    else{
        $this->cities = [];
        $this->state_id = '';
        $this->city_id = '';
    }
    return view('livewire.state-city', [
        'states' => State::all()->sortBy('state')
    ]);
}

}
`

@evildabbit I think because you have defaulted the tasks, users, and products to arrays, but then populate them with Eloquent results (a collection).

Try removing the array assignments and give it another shot ๐Ÿ‘. I.e.:

public function mount()
{
    $this->query = '';
}

Happy to help @evildabbit! :heart:

Strange! Maybe a composer update, caching issue, or something else... Glad it's working! ๐Ÿ‘

I have this issue on my edit component, url have id for the product id, when i do any change or call update function from .blade file i got this issue

In ComponentChecksumManager class, generate function, i printed the $stringForHashing variable and i got different string first on route to edit page and second on made any change in .blade

Id in first time is encrypted, second time decrypted

Route :
Route::livewire('products/edit/{id}', 'products.product-edit')->name('products.edit');

Check the image below for more details

packages versions :
"livewire/livewire": "^1.3"
"laravel/framework": "^7.24"

1

Hi @montaserfzy, can you post your component code?

Also, you may have to use this for your Route::livewire() call if you're using route-model binding:

Route::livewire('products/edit/{product}', 'products.product-edit')->name('products.edit');

//ProductsEdit.php
```namespace App\Http\Livewire\Products;

use App\Products;
use Livewire\Component;

class ProductEdit extends Component
{
public $name;
public $id;

public function __construct()
{
    //
}

public function mount($product)
{
    $this->id = $product;
}

public function render()
{
    return view('livewire.products.edit');
}

public function updateChanges()
{
    //
}

}

//edit.blade.php
```<div>
    @livewireStyles

    <div class="content"
         style="margin-top: 55px;">
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <div class="card">
                        <div class="card-body">
                            <div class="card-header card-header-primary mb-5">
                            </div>
                            <div>
                                <div class="row my-2">
                                    <div class="col-md-3">
                                        <input type="text" placeholder="name" wire:model="name" >

                                    </div>

                                </div>

                                <button type="button"
                                        class="btn btn-primary pull-right"
                                        wire:click="updateChanges" >Update
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

@livewireScripts 

This is the issue:

private $products = [];

You must use:

public $products;

Then, update your render() method to:

public function render()
{
    return view('livewire.products.index');
}

This property must be public for Livewire to be able to access it for subsequent requests ๐Ÿ‘

Don't worry -- as the information won't actually be public to the user itself, it's only public for rendering in the view.

Give that a shot and let me know!

Also, you may have to use this for your Route::livewire() call if you're using route-model binding:

Route::livewire('products/edit/{product}', 'products.product-edit')->name('products.edit');

the same issue

Oh and also, don't override the __construct method -- you must use the mount() method instead:

From:

public function __construct($id)
{
    parent::__construct($id);
    $this->products = Products::orderBy('created_at', 'desc')->get();
}

To:

public function mount($id)
{
    $this->products = Products::orderBy('created_at', 'desc')->get();
}

I'm unsure why you're supplying an $id, but not actually locating a specific product in your database. Regardless, the mount() method is what you're looking for.

still the issue on class

namespace Livewire;
class ComponentChecksumManager
{
    public function generate($name, $id, $data)
    {
        $hashKey = app('encrypter')->getKey();

        $stringForHashing = $name.$id.json_encode($data);

        var_dump($stringForHashing);
        return hash_hmac('sha256', $stringForHashing, $hashKey);
    }
    public function check($checksum, $name, $id, $data)
    {
        return hash_equals($this->generate($name, $id, $data), $checksum);
    }
}

Can you re-post your components code? I did update my first example:

From:

public $products = [];

To:

public $products;
<?php

namespace App\Http\Livewire\Products;

use Livewire\Component;

class ProductEdit extends Component
{
    public $name;
    public $product;

    public function __construct()
    {
        // do nothing
    }

    public function mount($product)
    {
        $this->product = $product;
    }

    public function render()
    {
        return view('livewire.products.edit');
    }

    public function updateChanges()
    {
        // do nothing 
    }

}

You are still overriding the __construct() method. Remove it completely from your component class.

I got this error
1

The solution which calebporzio commented on 12 Nov 2019 is fine for me; however if your app and your middleware (TrimStrings) is in a different namespace, it does not help; it took a while till I found out. I did not test it, but maybe one could use the Illuminate/Console/DetectsApplicationNamespace trait with getAppNamespace() to determine the correct namespace.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

basepack picture basepack  ยท  3Comments

stefro picture stefro  ยท  3Comments

austenc picture austenc  ยท  3Comments

bardh7 picture bardh7  ยท  3Comments

mokhosh picture mokhosh  ยท  3Comments