drizzle-team/drizzle-orm · error · Error

Cannot execute a query on a query builder. Please use a data

Error message

Cannot execute a query on a query builder. Please use a database instance instead.

What it means

PgSelectBase._prepare (select.ts:1080) throws when the query builder has no session, because executing requires a database connection to prepare the statement. A select built from a standalone QueryBuilder (new QueryBuilder()) or detached from a db instance carries no session and therefore cannot run.

Source

Thrown at drizzle-orm/src/pg-core/query-builders/select.ts:1081

	TSelectedFields = BuildSubquerySelection<TSelection, TNullabilityMap>,
> extends PgSelectQueryBuilderBase<
	PgSelectHKT,
	TTableName,
	TSelection,
	TSelectMode,
	TNullabilityMap,
	TDynamic,
	TExcludedMethods,
	TResult,
	TSelectedFields
> implements RunnableQuery<TResult, 'pg'>, SQLWrapper {
	static override readonly [entityKind]: string = 'PgSelect';

	/** @internal */
	_prepare(name?: string): PgSelectPrepare<this> {
		const { session, config, dialect, joinsNotNullableMap, authToken, cacheConfig, usedTables } = this;
		if (!session) {
			throw new Error('Cannot execute a query on a query builder. Please use a database instance instead.');
		}

		const { fields } = config;

		return tracer.startActiveSpan('drizzle.prepareQuery', () => {
			const fieldsList = orderSelectedFields<PgColumn>(fields);
			const query = session.prepareQuery<
				PreparedQueryConfig & { execute: TResult }
			>(dialect.sqlToQuery(this.getSQL()), fieldsList, name, true, undefined, {
				type: 'select',
				tables: [...usedTables],
			}, cacheConfig);
			query.joinsNotNullableMap = joinsNotNullableMap;

			return query.setToken(authToken);
		});
	}

View on GitHub (pinned to b7862528fd)

Solutions

  1. Build queries from a real db instance (drizzle(...)) so the session is attached: db.select().from(t).
  2. Pass the db into helper functions rather than constructing a standalone QueryBuilder.
  3. If you only need the SQL string, use qb.toSQL() or build the SQL without calling execute.

Example fix

// before
const qb = new QueryBuilder();
await qb.select().from(users).execute(); // no session -> error

// after
const db = drizzle(client);
await db.select().from(users).execute();
Defensive patterns

Strategy: validation

Validate before calling

// Ensure queries are built from a db instance, never a bare QueryBuilder.
function assertDb<T extends { session: unknown }>(db: T): asserts db is T & { session: object } {
  if (!db || !(db as any).session) {
    throw new Error('A db instance with a session is required to execute queries');
  }
}
assertDb(db);
await db.select().from(users).execute();

Type guard

function isBindableDb(db: unknown): db is { select: Function; execute: Function } {
  return db != null && typeof (db as any).select === 'function'
    && typeof (db as any).execute === 'function';
}

Prevention

When it happens

Trigger: Constructing a query with `new QueryBuilder()` and then calling .execute()/.prepare(); exporting a select builder without binding it to a db; passing a builder to a function that calls execute on it without a db.

Common situations: Trying to reuse query-construction helpers across modules by instantiating QueryBuilder directly; migrating from a raw SQL flow and forgetting to use the db instance; calling execute on a select returned from a test stub.

Related errors


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