Budibase/budibase · error

Unable to find table ID in request

Error message

Unable to find table ID in request

What it means

Row API handlers need to know which table (and optionally view) they operate on. getSourceId() resolves it from ctx.params.sourceId, ctx.params.tableId, or ctx.request.body.tableId, in that priority order. If none is present the request is malformed for the row API and this error is thrown, which surfaces as a 500 for the caller.

Source

Thrown at packages/server/src/api/controllers/row/utils/utils.ts:82

  if (ctx.params?.sourceId) {
    const { sourceId } = ctx.params
    if (isViewId(sourceId)) {
      return {
        tableId: getTableIdFromViewId(sourceId),
        viewId: sql.utils.encodeViewId(sourceId),
      }
    }
    return { tableId: sql.utils.encodeTableId(ctx.params.sourceId) }
  }
  // now check for old way of specifying table ID
  if (ctx.params?.tableId) {
    return { tableId: sql.utils.encodeTableId(ctx.params.tableId) }
  }
  // check body for a table ID
  if (ctx.request.body?.tableId) {
    return { tableId: sql.utils.encodeTableId(ctx.request.body.tableId) }
  }
  throw new Error("Unable to find table ID in request")
}

export async function getSource(ctx: Ctx): Promise<Table | ViewV2> {
  const { tableId, viewId } = getSourceId(ctx)
  if (viewId) {
    return sdk.views.get(viewId)
  }
  return sdk.tables.getTable(tableId)
}

export async function getTableFromSource(source: Table | ViewV2) {
  if (sdk.views.isView(source)) {
    return await sdk.views.getTable(source.id)
  }
  return source
}

function fixBooleanFields(row: Row, table: Table) {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Include the table ID in the URL path (e.g. /api/:tableId/rows or /api/:sourceId/rows).
  2. If using a body-based route, add tableId to the JSON body: { "tableId": "ta_...", ... }.
  3. Check that the variable interpolated into your request path/body is actually defined and non-empty.
  4. If targeting a view, use the view ID as sourceId — it resolves both tableId and viewId.

Example fix

// before
await api.post("/api/rows", { name: "x" })
// after
await api.post(`/api/${tableId}/rows`, { name: "x" })
Defensive patterns

Strategy: validation

Validate before calling

// validate request shape before calling the row API
function assertHasTableSource(opts: { path?: string; body?: Record<string, unknown> }) {
  const inPath = /\/(ta_|vd_)/.test(opts.path ?? "")
  const inBody = typeof opts.body?.tableId === "string" && opts.body.tableId.length > 0
  if (!inPath && !inBody) {
    throw new Error("Request must include a tableId or sourceId")
  }
}

Type guard

function hasTableId(body: unknown): body is { tableId: string } {
  return typeof body === "object" && body !== null && typeof (body as { tableId?: unknown }).tableId === "string"
}

Try / catch

try {
  return await api.get(`/api/${tableId}/rows`)
} catch (err) {
  if (err.message === "Unable to find table ID in request") {
    console.error("tableId missing from path/body — check interpolation")
  }
  throw err
}

Prevention

When it happens

Trigger: Any row endpoint (fetch/save/destroy/search) invoked without sourceId/tableId in the URL params AND without tableId in the request body; calling the API with a path that omits the table segment or sending a body missing the tableId field; custom/proxied requests built by hand that drop the table identifier.

Common situations: Hand-written curl/SDK calls to /api/rows-style endpoints missing the table ID; older integrations using deprecated URL shapes after the sourceId/tableId routing changed; template or automation code interpolating an empty/undefined tableId into the request path or body.

Related errors


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