Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization of 'Closure' is not allowed #891

Closed
ManuelLeiner opened this issue Dec 22, 2023 · 7 comments · Fixed by #893
Closed

Serialization of 'Closure' is not allowed #891

ManuelLeiner opened this issue Dec 22, 2023 · 7 comments · Fixed by #893
Labels

Comments

@ManuelLeiner
Copy link

Q A
Bug? yes
New Feature? no
Framework Laravel
Framework version 10.38.1
Package version 13.6.3
PHP version 8.2.14

Actual Behaviour

We audit a model App\Models\Project. The model has a slug column projects.slug which is managed by the spatie/laravel-sluggable package. Since the latest update from 13.5.1 to 13.6.3 creating a new project (Project::create([...])) will throw an error, see below. The user gets a 500 error message. The project is created. There is no audit entry.

We figured out that the error occurs as soon as we define an extraScope for the slug feature, see scopes.

Of course we can set the config audit.queue.enable to false and then the error is gone, too.

[2023-12-22 17:32:35] local.ERROR: Serialization of 'Closure' is not allowed {"userId":1,"exception":"[object] (Exception(code: 0): Serialization of 'Closure' is not allowed at /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/Queue.php:159)
[stacktrace]
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(159): serialize()
#1 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(128): Illuminate\\Queue\\Queue->createObjectPayload()
#2 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(106): Illuminate\\Queue\\Queue->createPayloadArray()
#3 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/SyncQueue.php(38): Illuminate\\Queue\\Queue->createPayload()
#4 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/SyncQueue.php(147): Illuminate\\Queue\\SyncQueue->push()
#5 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(72): Illuminate\\Queue\\SyncQueue->later()
#6 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(634): Illuminate\\Queue\\Queue->laterOn()
#7 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(552): Illuminate\\Events\\Dispatcher->queueHandler()
#8 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(478): Illuminate\\Events\\Dispatcher->Illuminate\\Events\\{closure}()
#9 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(286): Illuminate\\Events\\Dispatcher->Illuminate\\Events\\{closure}()
#10 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(266): Illuminate\\Events\\Dispatcher->invokeListeners()
#11 /var/www/html/vendor/owen-it/laravel-auditing/src/AuditableObserver.php(118): Illuminate\\Events\\Dispatcher->dispatch()
#12 /var/www/html/vendor/owen-it/laravel-auditing/src/AuditableObserver.php(41): OwenIt\\Auditing\\AuditableObserver->dispatchAudit()
#13 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(478): OwenIt\\Auditing\\AuditableObserver->created()
#14 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(286): Illuminate\\Events\\Dispatcher->Illuminate\\Events\\{closure}()
#15 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(266): Illuminate\\Events\\Dispatcher->invokeListeners()
#16 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php(188): Illuminate\\Events\\Dispatcher->dispatch()
#17 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1319): Illuminate\\Database\\Eloquent\\Model->fireModelEvent()
#18 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1137): Illuminate\\Database\\Eloquent\\Model->performInsert()
#19 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php(342): Illuminate\\Database\\Eloquent\\Model->save()
#20 /var/www/html/vendor/laravel/framework/src/Illuminate/Support/helpers.php(307): Illuminate\\Database\\Eloquent\\Relations\\HasOneOrMany->Illuminate\\Database\\Eloquent\\Relations\\{closure}()
#21 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php(339): tap()
#22 /var/www/html/app/Actions/CreateProject.php(21): Illuminate\\Database\\Eloquent\\Relations\\HasOneOrMany->create()
#23 /var/www/html/app/Http/Controllers/Web/ProjectController.php(66): App\\Actions\\CreateProject->__invoke()
#24 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): App\\Http\\Controllers\\Web\\ProjectController->store()

Expected Behaviour

We can create a project without error message. An audit entry is created and the slug is generated, respecting any extra scopes.

Steps to Reproduce

  • Create a fresh laravel project
  • Install composer require owen-it/laravel-auditing
  • publish config php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="config"
  • publish migration php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"
  • Install composer require spatie/laravel-sluggable
  • Define model Project with migration, two columns projects.name and projects.slug
  • Migrate
  • Make the model auditable
  • Make the model sluggable
  • Define an extraScope
  • Create a model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use OwenIt\Auditing\Auditable as AuditingAuditable;
use OwenIt\Auditing\Contracts\Auditable;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

class Project extends Model implements Auditable
{
    use HasFactory;
    use AuditingAuditable;
    use HasSlug;

    protected $fillable = [
        'name',
    ];

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions(): SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug')
            ->doNotGenerateSlugsOnUpdate()
            ->extraScope(fn ($builder) => $builder->whereNotNull('created_at')); // just for demonstration
    }
}
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('projects', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('projects');
    }
};
image
@ManuelLeiner
Copy link
Author

My guess:

During creation this property is set on the Project model instance.
https://github.com/spatie/laravel-sluggable/blob/main/src/HasSlug.php#L28

The property contains the closure / callback set by extraScope.
https://github.com/spatie/laravel-sluggable/blob/main/src/SlugOptions.php#L123

@parallels999
Copy link

parallels999 commented Dec 22, 2023

I think you should ask that on spatie/laravel-sluggable, with that, the model is not serializable
spatie/laravel-sluggable#254

@andycarrot
Copy link

We have encountered the same issue. Within the past couple of days. We had no problems with this package, then all of a sudden we are seeing 'Serialization of Closure' errors at version 16.6.3. This has caused a MASSIVE issue in our business and has me working out of hours to resolve it.

Rolling back to v13.5.1 fixed this issue.

We do not have the spatie/laravel-sluggable package installed. So there is another cause of this bug, which was introduced in a recent version of the owen-it/laravel-auditing package.

@parallels999
Copy link

parallels999 commented Dec 30, 2023

@andycarrot did you try #893

Also #884 (comment)

@MortenDHansen
Copy link
Contributor

MortenDHansen commented Dec 31, 2023

I have released 13.6.4 where the queue feature is disabled by default (as it should have been, sorry). I expect avoiding the serialization for queue should mitigate the problem. If not, let me know and stick to v13.5.1 in production.

@andycarrot
Copy link

andycarrot commented Jan 2, 2024

Hi @parallels999 and @MortenDHansen, thanks for your respoonses. I will try setting queue = false. But I think i'll stick on 13.5.1 on prod until i know this has been safely resolved in a future release, to avoid this happening again.

@MortenDHansen
Copy link
Contributor

Good idea. Sorry for the inconvenience!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants