{"record":{"id":"2241c9726b3923e6","repo":"sveltejs/kit","slug":"invalid-param-content-params-and-matcher-name","errorCode":null,"errorMessage":"Invalid param: ${content}. Params and matcher names can only have underscores, hyphens, and alphanumeric characters.","messagePattern":"Invalid param: (.+?)\\. Params and matcher names can only have underscores, hyphens, and alphanumeric characters\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/utils/routing.js","lineNumber":87,"sourceCode":"\n\t\t\t\t\t\t\tif (!segment) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst parts = segment.split(/\\[(.+?)\\](?!\\])/);\n\t\t\t\t\t\t\tconst result = parts\n\t\t\t\t\t\t\t\t.map((content, i) => {\n\t\t\t\t\t\t\t\t\tif (i % 2) {\n\t\t\t\t\t\t\t\t\t\tif (content.startsWith('x+') || content.startsWith('u+')) {\n\t\t\t\t\t\t\t\t\t\t\treturn escape(decode_escape_sequence(content.slice(2)));\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// We know the match cannot be null in the browser because manifest generation\n\t\t\t\t\t\t\t\t\t\t// would have invoked this during build and failed if we hit an invalid\n\t\t\t\t\t\t\t\t\t\t// param/matcher name with non-alphanumeric character.\n\t\t\t\t\t\t\t\t\t\tconst match = /** @type {RegExpExecArray} */ (param_pattern.exec(content));\n\t\t\t\t\t\t\t\t\t\tif (!BROWSER && !match) {\n\t\t\t\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t\t\t\t`Invalid param: ${content}. Params and matcher names can only have underscores, hyphens, and alphanumeric characters.`\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tconst [, is_optional, is_rest, name, matcher] = match;\n\t\t\t\t\t\t\t\t\t\t// It's assumed that the following invalid route id cases are already checked\n\t\t\t\t\t\t\t\t\t\t// - unbalanced brackets\n\t\t\t\t\t\t\t\t\t\t// - optional param following rest param\n\n\t\t\t\t\t\t\t\t\t\tparams.push({\n\t\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t\t\tmatcher,\n\t\t\t\t\t\t\t\t\t\t\toptional: !!is_optional,\n\t\t\t\t\t\t\t\t\t\t\trest: !!is_rest,\n\t\t\t\t\t\t\t\t\t\t\tchained: is_rest ? i === 1 && parts[0] === '' : false\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\treturn is_rest ? '([^]*?)' : is_optional ? '([^/]*)?' : '([^/]+?)';\n\t\t\t\t\t\t\t\t\t}","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/utils/routing.js#L69-L105","documentation":"SvelteKit validates route parameter and matcher names against a regex allowing only alphanumerics, underscores, and hyphens (plus the `=`/`...` syntax). During `parse_route_id`, if a bracketed parameter segment does not match that grammar, this error is thrown at build time. In the browser the exec result is assumed non-null because the build would have already rejected invalid names.","triggerScenarios":"A route file/id contains a parameter segment whose content fails `param_pattern.exec`, e.g. `[user name]`, `[id=match er]`, `[d@ta]`, or a matcher name with spaces or symbols passed to `parse_route_id` (directly or via `{ pattern }`/`{ pattern, params }` callers).","commonSituations":"Creating route folders with spaces or special characters like `[page id]`; mistyping a matcher separator, e.g. `[id match]` instead of `[id=match]`; copying route conventions from other frameworks that allow dots or slashes in param names.","solutions":["Rename the parameter to only use letters, digits, underscores, or hyphens (e.g. `[page_id]`)","Use `=` to separate param name from matcher name (`[id=integer]`, not `[id integer]`)","Remove invalid characters from the matcher name and update references in the params module"],"exampleFix":"// before (route folder)\nsrc/routes/[user id=role admin]/+page.svelte\n// after\nsrc/routes/[user_id=role]/+page.svelte","handlingStrategy":"validation","validationCode":"/^\\/?\\(?\\.{0,2}\\)?\\/?[a-zA-Z0-9_-]+(=[a-zA-Z0-9_-]+)?\\]?$/.test('[user_id=role]'); // validate folder names before creating them\nconst isValidParamName = (name) => /^[a-zA-Z0-9_-]+$/.test(name);","typeGuard":"function isValidRouteParam(segment) {\n\tconst inner = segment.replace(/^[[({]|[\\])}]$/g, '').replace(/^\\.\\.\\./, '');\n\tconst [name, matcher] = inner.split('=');\n\treturn /^[a-zA-Z0-9_-]+$/.test(name) && (matcher === undefined || /^[a-zA-Z0-9_-]+$/.test(matcher));\n}","tryCatchPattern":null,"preventionTips":["Use only letters, digits, `_`, `-` in route folder names and matcher names","Use `=` (not a space) to separate param from matcher","Avoid characters from other frameworks (dots, colons, spaces) in dynamic segments"],"tags":["routing","route-id","validation","build-time"],"backgroundTag":"invalid-route-id","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}