drizzle-team/drizzle-orm · error · DrizzleQueryError

Failed query: ${query} params: ${params}

Error message

Failed query: ${query}
params: ${params}

What it means

Wraps any underlying MySQL driver error in a DrizzleQueryError during query execution. This throw site (line 79) is the catch in MySqlPreparedQuery.queryWithCache for the no-cache path: cache is undefined, is a NoopCache, or query metadata is absent. Provides uniform error shape with SQL + params and the original driver error on .cause.

Source

Thrown at drizzle-orm/src/mysql-core/session.ts:79

		if (cache && cache.strategy() === 'all' && cacheConfig === undefined) {
			this.cacheConfig = { enable: true, autoInvalidate: true };
		}
		if (!this.cacheConfig?.enable) {
			this.cacheConfig = undefined;
		}
	}

	/** @internal */
	protected async queryWithCache<T>(
		queryString: string,
		params: any[],
		query: () => Promise<T>,
	): Promise<T> {
		if (this.cache === undefined || is(this.cache, NoopCache) || this.queryMetadata === undefined) {
			try {
				return await query();
			} catch (e) {
				throw new DrizzleQueryError(queryString, params, e as Error);
			}
		}

		// don't do any mutations, if globally is false
		if (this.cacheConfig && !this.cacheConfig.enable) {
			try {
				return await query();
			} catch (e) {
				throw new DrizzleQueryError(queryString, params, e as Error);
			}
		}

		// For mutate queries, we should query the database, wait for a response, and then perform invalidation
		if (
			(
				this.queryMetadata.type === 'insert' || this.queryMetadata.type === 'update'
				|| this.queryMetadata.type === 'delete'
			) && this.queryMetadata.tables.length > 0

View on GitHub (pinned to b7862528fd)

Solutions

  1. Inspect error.cause for the real MySQL driver error (mysql2 error code/message) and address it.
  2. Log error.query and error.params to reproduce the statement in a MySQL client.
  3. Verify connection config (host, port, credentials, ssl) in drizzle()/drizzleConfig.
  4. For deadlocks/lock timeouts, add retry logic or shorten transactions.

Example fix

// before
await db.select().from(users).where(eq(users.email, badEmail));

// after - inspect cause
import { DrizzleQueryError } from 'drizzle-orm/errors';
try {
  await db.select().from(users).where(eq(users.email, badEmail));
} catch (e) {
  if (e instanceof DrizzleQueryError) {
    console.error('SQL:', e.query, 'params:', e.params);
    console.error('driver cause:', e.cause);
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate inputs where possible; driver errors otherwise need try/catch
if (query == null) throw new Error('query required');

Type guard

import { DrizzleQueryError } from '~/errors.ts';
function isDrizzleQueryError(e: unknown): e is DrizzleQueryError {
  return e instanceof DrizzleQueryError;
}

Try / catch

try {
  await db.select().from(users).where(eq(users.id, id));
} catch (e) {
  if (e instanceof DrizzleQueryError) {
    logger.error({ sql: e.query, params: e.params, cause: e.cause });
  }
  throw e;
}

Prevention

When it happens

Trigger: Any execute/iterator/all/get/values call on a MySQL prepared query that fails at the driver level while no caching layer is active. This is the default execution path for MySQL.

Common situations: SQL syntax errors, connection failures, constraint violations, deadlocks, type mismatches between JS params and MySQL columns, or query timeouts against MySQL/PlanetScale.

Related errors


AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03). Data as JSON: /data/errors/468e3b8843972195.json. Report an issue: GitHub.