laravel/framework · error · LogicException

Please implement the prunable method on your model.

Error message

Please implement the prunable method on your model.

What it means

The plain Prunable trait (row-by-row pruning) provides a default prunable() that throws, requiring the model to override it with a query that returns the rows to prune. Without it, pruneAll() has no source query and the trait cannot run. This is contract enforcement identical in spirit to MassPrunable.

Solutions

  1. Implement prunable() on the model returning an Eloquent Builder selecting rows to prune.
  2. Choose MassPrunable instead if you want fast bulk deletes (both still need prunable()).
  3. Re-run php artisan model:prune after adding the method.

Example fix

// before
class OldSession extends Model
{
    use Prunable;
}

// after
class OldSession extends Model
{
    use Prunable;

    public function prunable()
    {
        return static::where('last_activity', '<', now()->subDay());
    }
}
Defensive patterns

Strategy: validation

Validate before calling

$reflection = new \ReflectionMethod($modelClass, 'prunable');
if ($reflection->getDeclaringClass()->getName() === \Illuminate\Database\Eloquent\Prunable::class) {
    throw new \RuntimeException("{$modelClass} uses Prunable without overriding prunable()");
}

Type guard

function overridesPrunableTrait(string $modelClass): bool {
    $r = new \ReflectionMethod($modelClass, 'prunable');
    return $r->getDeclaringClass()->getName() !== \Illuminate\Database\Eloquent\Prunable::class;
}

Prevention

When it happens

Trigger: Adding 'use Prunable;' to a model and calling Model::pruneAll() (or the model:prune command) without overriding prunable() to return a Builder.

Common situations: Setting up the scheduled model:prune command for the first time; using the wrong trait (Prunable vs MassPrunable) and forgetting the method; copying a model that omitted prunable().

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/4b9c97dc8d6fb337. Report an issue: GitHub.

Appendix: source

Thrown at src/Illuminate/Database/Eloquent/Prunable.php:59

                    }
                });

                event(new ModelsPruned(static::class, $total));
            });

        return $total;
    }

    /**
     * Get the prunable model query.
     *
     * @return \Illuminate\Database\Eloquent\Builder<static>
     *
     * @throws \LogicException
     */
    public function prunable()
    {
        throw new LogicException('Please implement the prunable method on your model.');
    }

    /**
     * Prune the model in the database.
     *
     * @return bool|null
     */
    public function prune()
    {
        $this->pruning();

        return static::isSoftDeletable()
            ? $this->forceDelete()
            : $this->delete();
    }

    /**
     * Prepare the model for pruning.

View on GitHub (pinned to e0f6eb3518)