Budibase/budibase · error · Error
Cannot generate query tool bindings without a query ID
Error message
Cannot generate query tool bindings without a query ID
What it means
getBindings generates AI tool bindings for a query, which requires a persisted document ID. If query._id is missing (unsaved or in-memory query object), it cannot build stable binding references and throws a plain Error before computing the tool type (REST_QUERY vs DATASOURCE_QUERY).
Source
Thrown at packages/server/src/sdk/workspace/ai/agents/queryToolReferences.ts:127
return {
...operation,
promptInstructions,
enabledTools,
}
})
return changed ? { ...agent, operations } : undefined
}
const getBindings = ({
datasource,
query,
}: {
datasource: Datasource
query: Query
}) => {
if (!query._id) {
throw new Error("Cannot generate query tool bindings without a query ID")
}
const sourceType: QueryToolType =
datasource.source === SourceName.REST
? ToolType.REST_QUERY
: ToolType.DATASOURCE_QUERY
return getQueryToolBindings({
sourceType,
sourceLabel:
datasource.name ||
(sourceType === ToolType.REST_QUERY ? "API" : "Datasource"),
queryName: query.name,
queryId: query._id,
})
}
export const migrateQueryToolReferences = async (
migrations: QueryToolReferenceMigration | QueryToolReferenceMigration[]
): Promise<void> => {View on GitHub (pinned to a81a902e9a)
Solutions
- Persist the query first (save/query API) so it has an _id, then call getBindings.
- Validate query._id in the calling code and skip or defer binding generation for unsaved queries.
- If constructing queries in tests/scripts, set a realistic _id before invoking getBindings.
Example fix
// before
getBindings({ datasource, query: draftQuery }) // throws
// after
const saved = await api.saveQuery(draftQuery)
if (!saved._id) throw new Error("Query must be saved")
getBindings({ datasource, query: saved }) Defensive patterns
Strategy: type-guard
Validate before calling
if (!query._id) {
throw new Error("Save the query before generating tool bindings")
}
getBindings({ datasource, query }) Type guard
const isPersistedQuery = (query: Query): query is Query & { _id: string } =>
typeof query._id === "string" && query._id.length > 0 Try / catch
try {
const bindings = getBindings({ datasource, query })
} catch (err) {
if ((err as Error).message.includes("without a query ID")) {
// defer binding generation until the query is saved
}
} Prevention
- Always persist queries before syncing agent tool bindings.
- Gate binding-generation code paths behind an _id check.
- In import/clone flows, save derived queries before computing bindings.
When it happens
Trigger: Calling getBindings({ datasource, query }) with a Query object that has not been saved to the database (_id undefined), e.g. building bindings for a newly drafted query before persisting it.
Common situations: Syncing query tool bindings during datasource import/edit flows before the query save completes; constructing a Query object manually in code or tests without an _id.
Related errors
- Agent _id is required
- Error getting status
- Unable to remove doc without a valid _id and _rev.
- Cannot store document without _id field.
- Configuration invalid. Must contain google clientID and clie
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/be027550cf2e0e68.
Report an issue: GitHub.