drizzle-team/drizzle-orm · error · Error

No value for placeholder "${p.name}" was provided

Error message

No value for placeholder "${p.name}" was provided

What it means

Thrown by fillPlaceholders() (sql.ts:616) when a Placeholder created via sql.placeholder('name') appears in the built parameter list but the supplied values record does not contain a key matching that name. fillPlaceholders is called when you execute a prepared query with placeholderValues. This form covers a bare Placeholder object.

Source

Thrown at drizzle-orm/src/sql/sql.ts:616

	declare protected: TValue;

	constructor(readonly name: TName) {}

	getSQL(): SQL {
		return new SQL([this]);
	}
}

/** @deprecated Use `sql.placeholder` instead. */
export function placeholder<TName extends string>(name: TName): Placeholder<TName> {
	return new Placeholder(name);
}

export function fillPlaceholders(params: unknown[], values: Record<string, unknown>): unknown[] {
	return params.map((p) => {
		if (is(p, Placeholder)) {
			if (!(p.name in values)) {
				throw new Error(`No value for placeholder "${p.name}" was provided`);
			}

			return values[p.name];
		}

		if (is(p, Param) && is(p.value, Placeholder)) {
			if (!(p.value.name in values)) {
				throw new Error(`No value for placeholder "${p.value.name}" was provided`);
			}

			return p.encoder.mapToDriverValue(values[p.value.name]);
		}

		return p;
	});
}

export type ColumnsSelection = Record<string, unknown>;

View on GitHub (pinned to b7862528fd)

Solutions

  1. Pass a values object that contains every placeholder name used in the query.
  2. Cross-check placeholder names against the values keys before executing.
  3. Default missing optional placeholders to null explicitly rather than omitting them.

Example fix

// before
const q = db.select().from(users).where(sql`${users.id} = ${sql.placeholder('uid')}`).prepare();
await q.all({}); // throws: No value for placeholder "uid"

// after
await q.all({ uid: 42 });
Defensive patterns

Strategy: validation

Validate before calling

function fillAllPlaceholders(query, values) {
  // collect placeholder names actually used
  const needed = new Set(query.toSQL().paramNames ?? []);
  const missing = [...needed].filter((n) => !(n in values));
  if (missing.length) throw new Error('Missing placeholders: ' + missing.join(', '));
  return query.all(values);
}

Type guard

const hasAllKeys = (obj, keys: string[]) =>
  keys.every((k) => k in obj && obj[k] !== undefined);

Prevention

When it happens

Trigger: Building a query with sql.placeholder('userId') then running .all({}) or .all({ otherKey: 1 }) — i.e. omitting the 'userId' key. Also when a placeholder name is misspelled or renamed between build and execute.

Common situations: Prepared queries reused across requests where a field was optional and left out; refactoring a placeholder name without updating every call site; spreading a partial object into placeholderValues.

Related errors


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