{"record":{"id":"9db80211fc867fde","repo":"n8n-io/n8n","slug":"querybuilder-parameter-keys-may-only-contain-numbe","errorCode":null,"errorMessage":"QueryBuilder parameter keys may only contain numbers, letters, underscores, or periods.","messagePattern":"QueryBuilder parameter keys may only contain numbers, letters, underscores, or periods\\.","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/query-builder/QueryBuilder.ts","lineNumber":363,"sourceCode":"\t */\n\thasParameter(key: string): boolean {\n\t\treturn this.parentQueryBuilder?.hasParameter(key) || key in this.expressionMap.parameters;\n\t}\n\n\t/**\n\t * Sets parameter name and its value.\n\t *\n\t * The key for this parameter may contain numbers, letters, underscores, or periods.\n\t */\n\tsetParameter(key: string, value: any): this {\n\t\tif (typeof value === 'function') {\n\t\t\tthrow new TypeORMError(\n\t\t\t\t`Function parameter isn't supported in the parameters. Please check \"${key}\" parameter.`,\n\t\t\t);\n\t\t}\n\n\t\tif (!key.match(/^([A-Za-z0-9_.]+)$/)) {\n\t\t\tthrow new TypeORMError(\n\t\t\t\t'QueryBuilder parameter keys may only contain numbers, letters, underscores, or periods.',\n\t\t\t);\n\t\t}\n\n\t\tif (this.parentQueryBuilder) {\n\t\t\tthis.parentQueryBuilder.setParameter(key, value);\n\t\t}\n\n\t\tthis.expressionMap.parameters[key] = value;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds all parameters from the given object.\n\t */\n\tsetParameters(parameters: ObjectLiteral): this {\n\t\tfor (const [key, value] of Object.entries(parameters)) {\n\t\t\tthis.setParameter(key, value);","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/query-builder/QueryBuilder.ts#L345-L381","documentation":"QueryBuilder.setParameter() validates the key against /^([A-Za-z0-9_.]+)$/ and throws if it fails. Parameter keys become placeholders in generated SQL; characters outside alphanumerics, underscore, and period would break parameter substitution or risk injection. Keys like 'a b', 'a-b', 'a$b' are rejected.","triggerScenarios":"Calling .setParameter('user id', val) (space), .setParameter('user-id', val) (hyphen), or any key with special characters. Also when building keys dynamically from untrusted input that contains symbols.","commonSituations":"Constructing parameter keys from form field names that contain spaces or hyphens. Copying a column name verbatim as a key. Typos or copy-paste introducing invisible characters.","solutions":["Use only letters, digits, underscore, and period in parameter keys.","Sanitize dynamic keys: key.replace(/[^A-Za-z0-9_.]/g, '_').","Prefer camelCase or snake_case keys consistently.","If a hyphenated identifier is needed, alias it to a safe key and map back."],"exampleFix":"// before\nqb.andWhere('u.role = :user-role', {})\n  .setParameter('user-role', role); // throws\n\n// after\nqb.andWhere('u.role = :userRole', {})\n  .setParameter('userRole', role);","handlingStrategy":"validation","validationCode":"const PARAM_KEY = /^([A-Za-z0-9_.]+)$/;\nfunction isValidParamKey(key: string): boolean { return PARAM_KEY.test(key); }\nif (!isValidParamKey(key)) throw new Error(`invalid parameter key: ${key}`);\nfunction sanitizeParamKey(key: string): string { return key.replace(/[^A-Za-z0-9_.]/g, '_'); }","typeGuard":"function isValidParamKey(key: string): key is string {\n  return /^([A-Za-z0-9_.]+)$/.test(key);\n}","tryCatchPattern":null,"preventionTips":["Restrict parameter keys to [A-Za-z0-9_.].","Sanitize dynamic keys: key.replace(/[^A-Za-z0-9_.]/g, '_').","Prefer camelCase or snake_case keys.","Validate keys from user input before setParameter."],"tags":["query-builder","parameters","validation","injection"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}