laravel/framework · error · LogicException

Cannot use saveOrIgnore on an existing model.

Error message

Cannot use saveOrIgnore on an existing model.

What it means

saveOrIgnore() inserts a new row ignoring unique-constraint conflicts (INSERT IGNORE semantics) and is only valid for models not yet persisted. The guard at the top rejects calls when $this->exists is true, because an existing model would need an UPDATE path, not an INSERT-OR-IGNORE.

Source

Thrown at src/Illuminate/Database/Eloquent/Model.php:1433

        // we need to happen after a model gets successfully saved right here.
        if ($saved) {
            $this->finishSave($options);
        }

        return $saved;
    }

    /**
     * Save the model to the database, ignoring specific unique constraint conflicts.
     *
     * @param  array  $options
     * @param  array|string|null  $uniqueBy
     * @return bool
     */
    public function saveOrIgnore(array $options = [], array|string|null $uniqueBy = null)
    {
        if ($this->exists) {
            throw new LogicException('Cannot use saveOrIgnore on an existing model.');
        }

        $this->mergeAttributesFromCachedCasts();

        $query = $this->newModelQuery();

        if ($this->fireModelEvent('saving') === false) {
            return false;
        }

        $saved = $this->performInsertOrIgnore($query, $uniqueBy);

        if (! $this->getConnectionName() &&
            $connection = $query->getConnection()) {
            $this->setConnection($connection->getName());
        }

        if ($saved) {

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Use save() or update() for existing models instead of saveOrIgnore().
  2. Instantiate a new model (new Model([...])) before calling saveOrIgnore() so $exists is false.
  3. For upsert behavior on existing rows, use upsert() or firstOrCreate()/updateOrCreate() depending on intent.

Example fix

// before
$user = User::find($id);
$user->saveOrIgnore(); // throws

// after
$user->save();
// or for insert-or-ignore on a new row:
User::createOrFirst(['email' => $email], [...]);
Defensive patterns

Strategy: type-guard

Validate before calling

if ($model->exists) {
    throw new \LogicException('Cannot saveOrIgnore on existing '.get_class($model).'; use save().');
}
$model->saveOrIgnore();

Type guard

function isInsertable(\Illuminate\Database\Eloquent\Model $model): bool {
    return ! $model->exists;
}

Prevention

When it happens

Trigger: Calling $existingModel->saveOrIgnore() on a model loaded from the database ($exists === true), e.g. reusing a fetched instance and attempting to insert-or-ignore it again.

Common situations: Treating saveOrIgnore as a generic upsert; passing a model retrieved via find()/first()/firstOrCreate() to saveOrIgnore instead of a freshly instantiated one; copy-paste from a create flow to an update flow.

Related errors


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