Budibase/budibase · error · HTTPError

View '${viewId}' not found in '${tableId}'

Error message

View '${viewId}' not found in '${tableId}'

What it means

Thrown by guardView in packages/server/src/sdk/workspace/rowActions/crud.ts when setting or unsetting a view-level permission for a view that either does not exist or does not belong to the given table. guardView only resolves the view when isViewId(viewId) is true, then verifies view.tableId matches tableId.

Source

Thrown at packages/server/src/sdk/workspace/rowActions/crud.ts:182

  const updated = await transformer(actionsDoc)

  const db = context.getWorkspaceDB()
  await db.put(updated)

  return {
    id: rowActionId,
    ...updated.actions[rowActionId],
  }
}

async function guardView(tableId: string, viewId: string) {
  let view
  if (isViewId(viewId)) {
    view = await sdk.views.get(viewId)
  }
  if (!view || view.tableId !== tableId) {
    throw new HTTPError(`View '${viewId}' not found in '${tableId}'`, 400)
  }
}

export async function setTablePermission(tableId: string, rowActionId: string) {
  return await updateDoc(tableId, rowActionId, async actionsDoc => {
    actionsDoc.actions[rowActionId].permissions.table.runAllowed = true
    return actionsDoc
  })
}

export async function unsetTablePermission(
  tableId: string,
  rowActionId: string
) {
  return await updateDoc(tableId, rowActionId, async actionsDoc => {
    actionsDoc.actions[rowActionId].permissions.table.runAllowed = false
    return actionsDoc
  })

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Pass a valid view id (formatted as a view id, e.g. 'data_view_...') rather than a table or row id.
  2. Confirm the view belongs to the same tableId you pass; fetch the view via sdk.views.get and compare tableId.
  3. Re-fetch the table's views list if the view may have been deleted recently.

Example fix

// before
await rowActions.setViewPermission(tableId, rowActionId, tableId /* wrong: table id as viewId */)
// after
const viewId = table.views["my_view"]?.id
if (viewId && isViewId(viewId)) await rowActions.setViewPermission(tableId, rowActionId, viewId)
Defensive patterns

Strategy: validation

Validate before calling

if (!isViewId(viewId)) throw new Error("setViewPermission requires a view id")
const view = await sdk.views.get(viewId)
if (!view || view.tableId !== tableId) throw new Error(`View ${viewId} is not part of table ${tableId}`)

Type guard

const isValidViewForTable = (view: View | undefined, tableId: string): view is View =>
  !!view && view.tableId === tableId

Try / catch

try {
  await rowActions.setViewPermission(tableId, rowActionId, viewId)
} catch (e) {
  if (e instanceof HTTPError && e.status === 400) {
    // wrong or missing view id: re-resolve from table.views
  } else throw e
}

Prevention

When it happens

Trigger: Calling setViewPermission/unsetViewPermission with a viewId that fails isViewId (so view stays undefined), a deleted view id, or a valid view id whose view.tableId differs from the supplied tableId.

Common situations: Passing a table id where a view id is expected; view deleted from the table while the client still holds its id; cross-table mix-up after copying permission code between tables.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/686038d2ea092fcf. Report an issue: GitHub.