laravel/framework · error · RuntimeException

This database engine does not support upserts.

Error message

This database engine does not support upserts.

What it means

The base Grammar::compileUpsert() throws because this engine has no single-statement upsert (INSERT ... ON DUPLICATE KEY / ON CONFLICT / MERGE) that the grammar can compile. All four bundled grammars override compileUpsert, so this base throw is only reached by a custom Grammar subclass that does not implement upserts.

Source

Thrown at src/Illuminate/Database/Query/Grammars/Grammar.php:1420

        $joins = $this->compileJoins($query, $query->joins);

        return "update {$table} {$joins} set {$columns} {$where}";
    }

    /**
     * Compile an "upsert" statement into SQL.
     *
     * @param  \Illuminate\Database\Query\Builder  $query
     * @param  array  $values
     * @param  array  $uniqueBy
     * @param  array  $update
     * @return string
     *
     * @throws \RuntimeException
     */
    public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
    {
        throw new RuntimeException('This database engine does not support upserts.');
    }

    /**
     * Prepare the bindings for an update statement.
     *
     * @param  array  $bindings
     * @param  array  $values
     * @return array
     */
    public function prepareBindingsForUpdate(array $bindings, array $values)
    {
        $cleanBindings = Arr::except($bindings, ['select', 'join']);

        $values = Arr::flatten(array_map(fn ($value) => value($value), $values));

        return array_values(
            array_merge($bindings['join'], $values, Arr::flatten($cleanBindings))
        );

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Implement compileUpsert($query, $values, $uniqueBy, $update) on the custom Grammar using the engine's native upsert syntax (e.g. MERGE).
  2. Switch to one of the bundled connections.
  3. Replace upsert() with a manual select-then-insert/update sequence.

Example fix

// before (custom grammar)
DB::table('users')->upsert($rows, ['email'], ['name']);
// throws base Grammar::compileUpsert

// after
protected function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
{
    // emit engine-native MERGE / ON CONFLICT equivalent
}
Defensive patterns

Strategy: validation

Validate before calling

$driver = $query->getConnection()->getDriverName();
if (! in_array($driver, ['mysql','sqlite','pgsql','sqlsrv'])) {
    throw new \LogicException('upsert is not supported by this engine.');
}
DB::table('users')->upsert($rows, ['email'], ['name']);

Type guard

function supportsUpsert(\Illuminate\Database\Connection $connection): bool
{
    return method_exists($connection->getQueryGrammar(), 'compileUpsert');
}

Prevention

When it happens

Trigger: Calling upsert($values, $uniqueBy, $update) on a connection whose grammar extends the base Grammar without overriding compileUpsert. No bundled driver reaches this base method.

Common situations: Building a new database driver integration that has not implemented upsert. Using a third-party grammar package that is incomplete.

Related errors


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