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

  1. Set a valid primary key on the model (protected $primaryKey = 'id';) matching an actual unique column.
  2. If the model truly has no primary key, delete via a direct query (Model::where(...)->delete()) instead of instance delete().
  3. 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

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


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