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.reduceView on GitHub (pinned to a81a902e9a)
Solutions
- Re-save the view in the builder so metadata is regenerated and stored.
- Verify the view's metadata document exists in the app DB (view meta records) and restore it from a backup if missing.
- 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
- Re-save legacy views after upgrading Budibase so metadata is generated.
- Verify view meta documents exist when importing app exports.
- Migrate legacy views to modern queries where possible.
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
- DB does not exist
- CouchDB error: ${err.message}
- View name is required
- Cannot delete rows through a calculation view
- Cannot delete rows through a calculation view
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/9db8719dde863fe0.
Report an issue: GitHub.