{"record":{"id":"66737a036ddef32b","repo":"Budibase/budibase","slug":"provided-edit-screen-route-is-invalid","errorCode":null,"errorMessage":"Provided edit screen route is invalid","messagePattern":"Provided edit screen route is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/builder/src/templates/screenTemplating/table/newScreen.ts","lineNumber":64,"sourceCode":"    .instanceName(`${tableOrView.name} - Create`)\n    .customProps({\n      hAlign: \"right\",\n      buttons: [createButton.json()],\n    })\n    .gridDesktopColSpan(7, 13)\n    .gridDesktopRowSpan(1, 3)\n\n  const heading = new Component(\"@budibase/standard-components/textv2\")\n    .instanceName(\"Table heading\")\n    .customProps({\n      text: `## ${tableOrView.name}`,\n    })\n    .gridDesktopColSpan(1, 7)\n    .gridDesktopRowSpan(1, 3)\n\n  const updateScreenRouteSegments = updateScreenRoute.split(\":id\")\n  if (updateScreenRouteSegments.length !== 2) {\n    throw new Error(\"Provided edit screen route is invalid\")\n  }\n\n  const tableBlock = new Component(\"@budibase/standard-components/gridblock\")\n    .instanceName(`${tableOrView.name} - Table`)\n    .customProps({\n      table: tableOrView.datasourceSelectFormat,\n      allowAddRows: false,\n      allowEditRows: false,\n      allowDeleteRows: false,\n      onRowClick: [\n        {\n          id: 0,\n          \"##eventHandlerType\": \"Navigate To\",\n          parameters: {\n            type: \"url\",\n            url: `${updateScreenRouteSegments[0]}{{ ${safe(\n              \"eventContext\"\n            )}.${safe(\"row\")}._id }}${updateScreenRouteSegments[1]}`,","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/builder/src/templates/screenTemplating/table/newScreen.ts#L46-L82","documentation":"getTableScreenTemplate builds the \"new screen\" table template, which needs an edit (detail) screen route containing a single `:id` parameter. It splits updateScreenRoute on \":id\" and requires exactly two segments (prefix and suffix) so it can splice a row-id binding into the route. Any route that doesn't contain exactly one `:id` placeholder makes the generated gridblock's row-click navigation impossible, so it throws.","triggerScenarios":"Calling getTableScreenTemplate (via tableScreenTemplate) with updateScreenRoute that has no `:id` (e.g. \"/dataperson\"), more than one `:id` (e.g. \"/person/:id/:id\"), or `:id` embedded in a way that yields != 2 segments after split.","commonSituations":"Programmatic screen generation passing a list-screen URL as the edit route; hand-constructed routes in scripts/plugins using `:id1`/`:Id` casing or `{id}` syntax instead of `:id`; routes copied from other frameworks using different param syntax.","solutions":["Make sure the edit-screen route contains exactly one `:id` segment, e.g. \"/person/:id\"","Fix param syntax/casing: must be lowercase `:id`, not `:ID`, `{id}`, or `:id1`","If a second param is needed, restructure the route so only one `:id` appears","Verify the route value passed from the calling UI (NewScreen flow) is the detail screen route, not the list screen route"],"exampleFix":"// before\ngetTableScreenTemplate({ updateScreenRoute: \"/person/edit\", ... })\n// after\ngetTableScreenTemplate({ updateScreenRoute: \"/person/:id\", ... })","handlingStrategy":"validation","validationCode":"function validateEditRoute(route: string) {\n  const segments = route.split(\":id\")\n  if (segments.length !== 2) {\n    throw new Error(`Edit route \"${route}\" must contain exactly one :id param`)\n  }\n}","typeGuard":"function hasSingleIdParam(route: string): boolean {\n  return route.split(\":id\").length === 2\n}","tryCatchPattern":"try {\n  return await tableScreenTemplate({ route, updateScreenRoute, ... })\n} catch (err) {\n  if ((err as Error).message === \"Provided edit screen route is invalid\") {\n    console.error(`Edit route \"${updateScreenRoute}\" lacks exactly one :id`)\n  }\n  throw err\n}","preventionTips":["Always build edit routes with a getValidRoute-style helper that enforces the \":id\" segment","Validate user-entered routes with a regex like /^\\/[^:]*:id$/ before passing them in","Don't reuse list-screen URLs as detail-screen routes","Watch for casing/synonym param syntax (:ID, {id}) when porting routes from other frameworks"],"tags":["builder","screens","routing"],"backgroundTag":"invalid-route-parameter","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}