{"id":"dc30e137658de258","repo":"drizzle-team/drizzle-orm","slug":"no-value-for-placeholder-p-name-was-provided","errorCode":null,"errorMessage":"No value for placeholder \"${p.name}\" was provided","messagePattern":"No value for placeholder \"(.+?)\" was provided","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/sql/sql.ts","lineNumber":616,"sourceCode":"\tdeclare protected: TValue;\n\n\tconstructor(readonly name: TName) {}\n\n\tgetSQL(): SQL {\n\t\treturn new SQL([this]);\n\t}\n}\n\n/** @deprecated Use `sql.placeholder` instead. */\nexport function placeholder<TName extends string>(name: TName): Placeholder<TName> {\n\treturn new Placeholder(name);\n}\n\nexport function fillPlaceholders(params: unknown[], values: Record<string, unknown>): unknown[] {\n\treturn params.map((p) => {\n\t\tif (is(p, Placeholder)) {\n\t\t\tif (!(p.name in values)) {\n\t\t\t\tthrow new Error(`No value for placeholder \"${p.name}\" was provided`);\n\t\t\t}\n\n\t\t\treturn values[p.name];\n\t\t}\n\n\t\tif (is(p, Param) && is(p.value, Placeholder)) {\n\t\t\tif (!(p.value.name in values)) {\n\t\t\t\tthrow new Error(`No value for placeholder \"${p.value.name}\" was provided`);\n\t\t\t}\n\n\t\t\treturn p.encoder.mapToDriverValue(values[p.value.name]);\n\t\t}\n\n\t\treturn p;\n\t});\n}\n\nexport type ColumnsSelection = Record<string, unknown>;","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/sql/sql.ts#L598-L634","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a values object that contains every placeholder name used in the query.","Cross-check placeholder names against the values keys before executing.","Default missing optional placeholders to null explicitly rather than omitting them."],"exampleFix":"// before\nconst q = db.select().from(users).where(sql`${users.id} = ${sql.placeholder('uid')}`).prepare();\nawait q.all({}); // throws: No value for placeholder \"uid\"\n\n// after\nawait q.all({ uid: 42 });","handlingStrategy":"validation","validationCode":"function fillAllPlaceholders(query, values) {\n  // collect placeholder names actually used\n  const needed = new Set(query.toSQL().paramNames ?? []);\n  const missing = [...needed].filter((n) => !(n in values));\n  if (missing.length) throw new Error('Missing placeholders: ' + missing.join(', '));\n  return query.all(values);\n}","typeGuard":"const hasAllKeys = (obj, keys: string[]) =>\n  keys.every((k) => k in obj && obj[k] !== undefined);","tryCatchPattern":null,"preventionTips":["Define placeholder names as constants and reuse them at build and call sites.","Audit prepared queries after renaming any placeholder.","Default optional placeholders to null instead of omitting them."],"tags":["placeholders","prepared-query","params"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}