laravel/framework · error · LogicException
No primary key defined on model.
Error message
No primary key defined on model.
What it means
delete() checks getKeyName(); if it returns null (no primary key declared on the model), the model cannot be deleted by key and a LogicException is thrown. This usually means $primaryKey was unset/null or the model intentionally has no primary key (e.g. a pivot/view), making deletion unsupported.
Source
Thrown at src/Illuminate/Database/Eloquent/Model.php:1740
}
}
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 bd6b5437e6)
Solutions
- Set a valid primary key on the model (protected $primaryKey = 'id';) matching an actual unique column.
- If the model truly has no primary key, delete via a direct query (Model::where(...)->delete()) instead of instance delete().
- For pivot tables, use the detach()/attach() API on the relationship rather than deleting pivot model instances.
Example fix
// before
class UserView extends Model {
protected $primaryKey = null;
}
$view->delete(); // throws
// after
UserView::where('id', $view->id)->delete(); Defensive patterns
Strategy: type-guard
Validate before calling
if (is_null($model->getKeyName())) {
// delete by query instead of instance
(get_class($model))::where(get_class($model)::query()->getQuery()->from, $model->getOriginal(...))->delete();
}
$model->delete(); Type guard
function hasPrimaryKey(\Illuminate\Database\Eloquent\Model $model): bool {
return ! is_null($model->getKeyName());
} Try / catch
try {
$model->delete();
} catch (\LogicException $e) {
if (str_contains($e->getMessage(), 'No primary key')) {
get_class($model)::query()->where(...)->delete();
}
} Prevention
- Define a real $primaryKey on models that need instance delete().
- Use query-based deletion for view/pivot models without a key.
- Validate getKeyName() in adapters that wrap deletion.
When it happens
Trigger: Calling $model->delete() on a model whose protected $primaryKey is set to null or empty, or on a model class where the primary key was intentionally removed (e.g. a read-only DB view mapped as a model).
Common situations: Mapping a database view or a join-table without a single key column; setting $primaryKey = null by mistake; using a base model class that nulls the key.
Related errors
- SQLite does not support altering primary keys.
- The chunkById operation was aborted because the [{$alias}] c
- The lazyById operation was aborted because the [{$alias}] co
- No record found for the given query.
- $count records were found.
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/9ce2ccbffa0de818.json.
Report an issue: GitHub.