Budibase/budibase · error · HTTPError
view is missing queryUI field
Error message
view is missing queryUI field
What it means
ensureQueryUISet normalizes a ViewV2 so that its `queryUI` field is populated from `query`. Views persist filters as either LegacyFilter[] (array form) or SearchFilters (object form). The code can only convert the legacy array form to queryUI; if `query` is a non-empty object (SearchFilters) but `queryUI` is missing, there is no safe conversion, so it throws a 400 HTTPError.
Source
Thrown at packages/server/src/sdk/workspace/views/utils.ts:38
}
export function ensureQueryUISet(viewArg: Readonly<ViewV2>): ViewV2 {
const view = cloneDeep<ViewV2>(viewArg)
if (!view.queryUI && view.query && !isEmptyObject(view.query)) {
if (!Array.isArray(view.query)) {
// In practice this should not happen. `view.query`, at the time this code
// goes into the codebase, only contains LegacyFilter[] in production.
// We're changing it in the change that this comment is part of to also
// include SearchFilters objects. These are created when we receive an
// update to a ViewV2 that contains a queryUI and not a query field. We
// can convert UISearchFilter (the type of queryUI) to SearchFilters,
// but not LegacyFilter[], they are incompatible due to UISearchFilter
// and SearchFilters being recursive types.
//
// So despite the type saying that `view.query` is a LegacyFilter[] |
// SearchFilters, it will never be a SearchFilters when a `view.queryUI`
// is specified, making it "safe" to throw an error here.
throw new HTTPError("view is missing queryUI field", 400)
}
view.queryUI = utils.processSearchFilters(view.query)
}
return view
}
export function ensureQuerySet(viewArg: Readonly<ViewV2>): ViewV2 {
const view = cloneDeep<ViewV2>(viewArg)
// We consider queryUI to be the source of truth, so we don't check for the
// presence of query here. We will overwrite it regardless of whether it is
// present or not.
if (view.queryUI && !isEmptyObject(view.queryUI)) {
view.query = dataFilters.buildQuery(view.queryUI)
}
return view
}
View on GitHub (pinned to a81a902e9a)
Solutions
- Check the offending view doc in the workspace DB and either add a `queryUI` field (UISearchFilter form) or convert `query` back to the LegacyFilter[] array form
- Re-save the view through the builder UI so the server writes both `query` and `queryUI` via ensureQuerySet
- If programmatically creating views via the API, send `queryUI` (not a SearchFilters-shaped `query`)
- Delete and recreate the corrupted view if its filters are not needed
Example fix
// before (API payload that triggers the error)
{ "name": "MyView", "query": { "equal": { "status": "live" } } }
// after
{ "name": "MyView", "queryUI": { "onGroups": [{ "operator": "equal", "field": "status", "value": "live" }] } } Defensive patterns
Strategy: validation
Validate before calling
function canProcessView(view) {
const hasQuery = view.query && Object.keys(view.query).length > 0
return !(hasQuery && !Array.isArray(view.query) && !view.queryUI)
}
if (!canProcessView(view)) throw new Error('View needs queryUI or array-form query') Type guard
function hasConvertibleQuery(view) {
return !view.query || Array.isArray(view.query) || !!view.queryUI
} Try / catch
try {
const enriched = await sdk.views.get(viewId)
} catch (e) {
if (e?.status === 400 && e?.message?.includes('queryUI')) {
// recreate or repair the view doc
} else throw e
} Prevention
- Always create/update views through the SDK/API so queryUI is written alongside query
- Never hand-edit view docs in CouchDB
- After upgrading, audit views for object-shaped query without queryUI
When it happens
Trigger: Any of processTable, get, getEnriched, create, update, or enrichedViews loads/accepts a view whose `query` is a non-empty SearchFilters object while `queryUI` is undefined/null. This happens when a view doc was persisted with SearchFilters-shaped query data but without the queryUI field (e.g. written by code that bypassed ensureQuerySet, hand-edited docs, or docs from a version before queryUI existed).
Common situations: Upgrading Budibase and hitting views migrated from older versions; importing/exporting apps where view docs were edited externally; writing directly to CouchDB or via scripts that set `query` without `queryUI`; partial API calls that sent `query` instead of `queryUI` on view create/update.
Related errors
- Project package contains invalid datasource entities.
- View '${viewId}' not found in '${tableId}'
- Cannot insert rows through a calculation view
- Cannot update view type after creation
- Duplicate calculation on field "${schema.field}", calculatio
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/ff13b03d2d35eda4.
Report an issue: GitHub.