{"record":{"id":"fa823321f08bfd8a","repo":"cockroachdb/cockroach","slug":"table-id-is-required","errorCode":null,"errorMessage":"Table ID is required","messagePattern":"Table ID is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pkg/ui/workspaces/cluster-ui/src/api/getTableMetadataApi.ts","lineNumber":182,"sourceCode":null,"sourceCodeStart":null,"sourceCodeEnd":null,"githubUrl":"https://github.com/cockroachdb/cockroach/blob/8812064a015d2faf99d3fc7e15880f94042954b0/pkg/ui/workspaces/cluster-ui/src/api/getTableMetadataApi.ts#L182","documentation":"getTableDetails in cluster-ui throws 'Table ID is required' before any network call when req.tableId is falsy (undefined, 0) or NaN. It guards the REST fetch to `${TABLE_METADATA_API_PATH}${req.tableId}/`, which would otherwise produce a malformed URL or a 404 for '/table_metadata/NaN/'. Typically the caller (useTableDetails SWR hook) received an unparsed or non-numeric id.","triggerScenarios":"Calling getTableDetails/useTableDetails with an id built from a missing route param (Number(undefined) = NaN), a non-numeric string id (Number('abc')), or an unset selection in the table details panel.","commonSituations":"Deep links to a table-details route where the id segment is empty or a table name instead of the numeric id; list rows that lack a tableId (dropped tables, views); details panel rendered before a row selection resolves.","solutions":["Validate the route/prop before rendering the hook: parse once and fall back to an empty state if not a positive integer","Pass the numeric metadata id (e.g. row's tableId field), not the table name","Enforce numeric route patterns so unmatched URLs never reach the component"],"exampleFix":"// before\nconst tableId = Number(props.match.params.id);\nconst { data } = useTableDetails({ tableId });\n\n// after\nconst tableId = Number(props.match.params.id);\nif (!Number.isInteger(tableId) || tableId <= 0) {\n  return <EmptyState title='Select a table to see details' />;\n}\nconst { data } = useTableDetails({ tableId });","handlingStrategy":"validation","validationCode":"const tableId = Number(rawId);\nif (!Number.isInteger(tableId) || tableId <= 0) {\n  return <EmptyState title='Select a table to see details' />;\n}\nconst { data } = useTableDetails({ tableId });","typeGuard":"const isValidTableId = (id: unknown): id is number =>\n  typeof id === 'number' && Number.isInteger(id) && id > 0;","tryCatchPattern":"try {\n  const details = await getTableDetails(req);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Table ID is required') {\n    return <EmptyState title='Select a table to see details' />;\n  }\n  throw e;\n}","preventionTips":["Derive tableId only from table metadata rows that guarantee a numeric id","Enforce numeric route segments so bad URLs never mount the details component","Default SWR hooks off until an id is confirmed valid (conditional keys)"],"tags":["cluster-ui","table-metadata","validation","typescript","swr"],"backgroundTag":null,"analyzedSha":"8812064a015d2faf99d3fc7e15880f94042954b0","analyzedAt":"2026-08-15T16:34:17.351Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}