Budibase/budibase · error · Error

Legacy view metadata is missing

Error message

Legacy view metadata is missing

What it means

`runView` executes a legacy (CouchDB-style) view whose metadata (`view.meta`) was rebuilt from stored data. Because map/reduce strings are not executed directly (untrusted code), the metadata object is required to reconstruct the view via viewBuilder. When the stored view has no meta, runView cannot rebuild it and throws 'Legacy view metadata is missing'.

Source

Thrown at packages/server/src/db/inMemoryView.ts:29

  view: DBView,
  calculation: string,
  group: boolean,
  data: Row[]
) {
  // use a different ID each time for the DB, make sure they
  // are always unique for each query, don't want overlap
  // which could cause 409s
  const db = new Pouch(utils.newid())
  try {
    // write all the docs to the in memory Pouch (remove revs)
    await db.bulkDocs(
      data.map(row => ({
        ...row,
        _rev: undefined,
      }))
    )
    if (!view.meta) {
      throw new Error("Legacy view metadata is missing")
    }

    // Rebuild map/reduce from metadata to avoid executing untrusted map strings.
    const groupByMulti =
      view.meta.groupByMulti ?? view.meta.schema?.group?.type === "array"
    const rebuiltView = viewBuilder(view.meta as any, groupByMulti)
    let fn = (doc: Document, emit: any) => emit(doc._id)
    // BUDI-7060 -> indirect eval call appears to cause issues in cloud
    eval(
      "fn = " +
        rebuiltView?.map?.replace("function (doc)", "function (doc, emit)")
    )
    const queryFns: any = {
      meta: rebuiltView.meta,
      map: fn,
    }
    if (rebuiltView.reduce) {
      queryFns.reduce = rebuiltView.reduce

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Re-save the view in the builder so metadata is regenerated and stored.
  2. Verify the view's metadata document exists in the app DB (view meta records) and restore it from a backup if missing.
  3. Replace usage of the legacy view with a modern query or the in-memory view calculation path.

Example fix

// before
const rows = await fetchLegacyView(table, "groupName") // meta missing
// after: recreate the view via API so meta is persisted
await api.post(`/tables/${tableId}/views`, { name: "groupName", ...def })
Defensive patterns

Strategy: try-catch

Validate before calling

// check the view has metadata before querying
const view = await db.get<View>(`view_${viewName}`) // or app meta lookup
if (!view.meta) throw new Error(`Legacy view '${viewName}' has no metadata; recreate it before querying`)

Try / catch

try {
  return await runView({ table, viewName, params })
} catch (err) {
  if (err.message === "Legacy view metadata is missing") {
    // recreate the view from its definition then retry once
    await recreateLegacyView(table, viewName)
    return await runView({ table, viewName, params })
  }
  throw err
}

Prevention

When it happens

Trigger: Calling fetchLegacyView for a view whose metadata document is absent or was not migrated (view.meta undefined) — e.g. querying a table's legacy view after an app import/upgrade where the meta doc was lost or never created.

Common situations: Upgrading old Budibase apps that predate the metadata-based view storage; views referenced in code that were created by another tool directly in CouchDB; partially failed migrations leaving view rows without their meta companion.

Related errors


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