laravel/framework · error · LogicException
No primary key defined on model.
Error message
No primary key defined on model.
What it means
delete() throws when getKeyName() returns null, i.e. the model declares no primary key (protected $primaryKey = null or it was never set and the base default was removed). Without a primary key Eloquent cannot build the DELETE WHERE clause, so it refuses rather than issue a dangerous table-wide delete.
Solutions
- Set a real primary key column: protected $primaryKey = 'id';.
- If the table genuinely has no PK, perform the delete via the query builder: DB::table('table')->where(...)->delete();.
- For composite keys, this guard still applies - Eloquent's delete() needs a single key; override delete() in the model to build the WHERE manually.
Example fix
// before
class UserView extends Model
{
protected $table = 'user_view';
protected $primaryKey = null;
}
$view->delete(); // throws
// after - delete via query builder
DB::table('user_view')->where('user_id', $id)->delete(); Defensive patterns
Strategy: validation
Validate before calling
if (! $model->getKeyName()) {
// delete via the query builder instead
return \DB::table($model->getTable())->where($where)->delete();
}
return $model->delete(); Type guard
function hasPrimaryKey(\Illuminate\Database\Eloquent\Model $m): bool {
return $m->getKeyName() !== null && $m->getKeyName() !== '';
} Try / catch
try {
$model->delete();
} catch (\LogicException $e) {
if (str_contains($e->getMessage(), 'No primary key')) {
\DB::table($model->getTable())->where('id', $model->id)->delete();
} else { throw $e; }
} Prevention
- Set protected $primaryKey on models backed by real tables.
- For view/junction models without a PK, delete via DB::table() with an explicit WHERE.
- Audit models where you intentionally null $primaryKey to ensure no delete() calls reach them.
When it happens
Trigger: Defining a model with protected $primaryKey = null (or unset), or a model that intentionally has no PK column (e.g. a view), then calling $model->delete().
Common situations: Models backed by database views or junction tables without a PK; overriding $primaryKey to an empty value by mistake; dynamic configuration that nulls the key; soft-delete on a PK-less model.
Related errors
- Collection given to whereAttachedTo method may not be empty.
- Collection given to whereBelongsTo method may not be empty.
- Collection given to whereMorphedTo method may not be empty.
- Collection given to whereNotMorphedTo method may not be…
- $count records were found.
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/9ce2ccbffa0de818.
Report an issue: GitHub.
Appendix: source
Thrown at src/Illuminate/Database/Eloquent/Model.php:1742
}
}
return $count;
}
/**
* Delete the model from the database.
*
* @return bool|null
*
* @throws \LogicException
*/
public function delete()
{
$this->mergeAttributesFromCachedCasts();
if (is_null($this->getKeyName())) {
throw new LogicException('No primary key defined on model.');
}
// If the model doesn't exist, there is nothing to delete so we'll just return
// immediately and not do anything else. Otherwise, we will continue with a
// deletion process on the model, firing the proper events, and so forth.
if (! $this->exists) {
return;
}
if ($this->fireModelEvent('deleting') === false) {
return false;
}
// Here, we'll touch the owning models, verifying these timestamps get updated
// for the models. This will allow any caching to get broken on the parents
// by the timestamp. Then we will go ahead and delete the model instance.
$this->touchOwners();
View on GitHub (pinned to e0f6eb3518)