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 Prunable trait (per-model delete-based pruning) provides a default prunable() that throws this LogicException. Unlike MassPrunable, Prunable deletes row-by-row after chunking, but still requires the model to override prunable() to return the query selecting records to prune.

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 bd6b5437e6)

Solutions

  1. Implement public function prunable() returning a Builder that selects the records to prune.
  2. Confirm the trait in use matches your intent (MassPrunable for bulk, Prunable for per-model pruning hooks).
  3. Implement the pruning() hook if you also need side effects before each delete.

Example fix

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

// after
class Document extends Model {
    use Prunable;

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

Strategy: type-guard

Validate before calling

$reflection = new \ReflectionMethod($modelClass, 'prunable');
if ($reflection->getDeclaringClass()->getName() === \Illuminate\Database\Eloquent\Prunable::class) {
    throw new \LogicException("{$modelClass} must override prunable() before pruning.");
}

Type guard

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

Prevention

When it happens

Trigger: Adding 'use Prunable;' to a model and running Model::pruneAll() or model:prune without overriding prunable().

Common situations: Adopting Prunable for cleanup tasks and forgetting the override; switching between MassPrunable and Prunable and missing the method; artisan model:prune failing on a newly-tagged model.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/4b9c97dc8d6fb337.json. Report an issue: GitHub.