{"record":{"id":"636d2dd549daf722","repo":"withastro/astro","slug":"invalid-route-file-rest-parameter-must-be-a-s","errorCode":null,"errorMessage":"Invalid route ${file} — rest parameter must be a standalone segment","messagePattern":"Invalid route (.+?) — rest parameter must be a standalone segment","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/core/routing/segment.ts","lineNumber":14,"sourceCode":"export function validateSegment(segment: string, file = '') {\n\tif (!file) file = segment;\n\n\tif (segment.includes('][')) {\n\t\tthrow new Error(`Invalid route ${file} \\u2014 parameters must be separated`);\n\t}\n\tif (countOccurrences('[', segment) !== countOccurrences(']', segment)) {\n\t\tthrow new Error(`Invalid route ${file} \\u2014 brackets are unbalanced`);\n\t}\n\tif (\n\t\t(/.+\\[\\.\\.\\.[^\\]]+\\]/.test(segment) || /\\[\\.\\.\\.[^\\]]+\\].+/.test(segment)) &&\n\t\tfile.endsWith('.astro')\n\t) {\n\t\tthrow new Error(`Invalid route ${file} \\u2014 rest parameter must be a standalone segment`);\n\t}\n}\n\nfunction countOccurrences(needle: string, haystack: string) {\n\tlet count = 0;\n\tfor (const hay of haystack) {\n\t\tif (hay === needle) count += 1;\n\t}\n\treturn count;\n}\n","sourceCodeStart":1,"sourceCodeEnd":25,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/core/routing/segment.ts#L1-L25","documentation":"A rest parameter [...rest] in an .astro route must occupy the entire segment; it cannot be combined with other characters in the same filename. validateSegment rejects names matching /.+[...x]/ or /[...x].+/ when the file ends with .astro. (This restriction is specific to .astro files.)","triggerScenarios":"An .astro filename where a catch-all [...slug] is adjacent to literal text, e.g. src/pages/post-[...slug].astro, src/pages/[...path]index.astro, or src/pages/blog[...rest].astro.","commonSituations":"Trying to prefix or suffix a catch-all route; migrating a wildcard and leaving text around the rest parameter; using [...rest] alongside a static word.","solutions":["Make the rest parameter its own standalone segment via a folder/file, e.g. src/pages/post/[...slug].astro.","Remove any literal text adjacent to the [...rest] token.","If you need a prefix, nest directories instead of concatenating text to the rest parameter."],"exampleFix":"// before\nsrc/pages/post-[...slug].astro\n// after\nsrc/pages/post/[...slug].astro","handlingStrategy":"validation","validationCode":"function isStandaloneRestSegment(fileName) {\n  if (!fileName.endsWith('.astro')) return true;\n  return !(/.+\\[\\.\\.\\.[^\\]]+\\]/.test(fileName) || /\\[\\.\\.\\.[^\\]]+\\].+/.test(fileName));\n}\nfor (const f of routeFiles) {\n  if (!isStandaloneRestSegment(f)) throw new Error(`Rest param must be standalone in ${f}`);\n}","typeGuard":"const isStandaloneRest = (name: string): boolean =>\n  !(name.endsWith('.astro') && (/.+\\[\\.\\.\\.[^\\]]+\\]/.test(name) || /\\[\\.\\.\\.[^\\]]+\\].+/.test(name)));","tryCatchPattern":null,"preventionTips":["Keep catch-all [...rest] as the only text in its filename.","Use nested folders to add prefixes instead of text in the filename.","Remember the rule applies to .astro files specifically."],"tags":["routing","build","rest-param"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}