{"record":{"id":"fe3637ac97fadcce","repo":"Budibase/budibase","slug":"view-view-id-not-found-in-table-tableid-fe3637","errorCode":null,"errorMessage":"View ${view.id} not found in table ${tableId}","messagePattern":"View (.+?) not found in table (.+?)","errorType":"http","errorClass":"HTTPError","httpStatus":404,"severity":"error","filePath":"packages/server/src/sdk/workspace/views/internal.ts","lineNumber":76,"sourceCode":"\n  table.views[view.name] = view\n  await db.put(table)\n  return view\n}\n\nexport async function update(\n  tableId: string,\n  view: Readonly<ViewV2>\n): Promise<{ view: ViewV2; existingView: ViewV2 }> {\n  const db = context.getWorkspaceDB()\n  const table = await sdk.tables.getTable(tableId)\n  table.views ??= {}\n\n  const existingView = Object.values(table.views).find(\n    v => isV2(v) && v.id === view.id\n  )\n  if (!existingView || !existingView.name) {\n    throw new HTTPError(`View ${view.id} not found in table ${tableId}`, 404)\n  }\n\n  if (isV2(existingView) && existingView.type !== view.type) {\n    throw new HTTPError(`Cannot update view type after creation`, 400)\n  }\n\n  view = ensureQuerySet(view)\n  view = ensureQueryUISet(view)\n\n  delete table.views[existingView.name]\n  table.views[view.name] = view\n  await db.put(table)\n  return { view, existingView } as { view: ViewV2; existingView: ViewV2 }\n}\n\nexport async function remove(viewId: string): Promise<ViewV2> {\n  const db = context.getWorkspaceDB()\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/views/internal.ts#L58-L94","documentation":"sdk.views.update looks up the existing view in the table by view.id and requires it to exist (with a name). If the id doesn't correspond to any view on the table, an HTTPError 404 'View ${view.id} not found in table ${tableId}' is thrown rather than silently creating.","triggerScenarios":"Calling sdk.views.update(view) where view.id is not present among table.views — view was deleted, id belongs to another table, or update was called instead of create.","commonSituations":"Client caches a stale view id after deletion; passing a V1 view id; tableId mismatch when moving views; race with a concurrent delete.","solutions":["Call sdk.views.create instead of update if the view doesn't exist yet.","Re-fetch the correct view id from the table before updating.","Confirm the viewId's embedded tableId matches the table you pass.","Handle the 404 and recreate the view if it was legitimately deleted."],"exampleFix":"// before\nawait sdk.views.update({ id: staleId, ...view })\n// after\nconst table = await sdk.tables.getTable(tableId)\nconst exists = Object.values(table.views ?? {}).some(v => isV2(v) && v.id === staleId)\nif (!exists) {\n  await sdk.views.create({ tableId, name: view.name, ...view })\n} else {\n  await sdk.views.update({ id: staleId, ...view })\n}","handlingStrategy":"try-catch","validationCode":"const table = await sdk.tables.getTable(tableId)\nif (!Object.values(table.views ?? {}).some(v => isV2(v) && v.id === view.id)) {\n  await sdk.views.create({ ...view, tableId })\n} else {\n  await sdk.views.update(view)\n}","typeGuard":"function viewExistsInTable(view: ViewV2, table: Table): boolean {\n  return Object.values(table.views ?? {}).some(v => isV2(v) && v.id === view.id)\n}","tryCatchPattern":"try {\n  await sdk.views.update(view)\n} catch (e) {\n  if (e instanceof HTTPError && e.status === 404) {\n    await sdk.views.create({ ...view, tableId })\n  } else { throw e }\n}","preventionTips":["Always fetch fresh view ids from the table before updating","Use upsert logic (check existence then create/update)","Confirm the viewId's tableId matches the table being updated"],"tags":["not-found","views","http-404"],"backgroundTag":"resource-not-found","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}