Budibase/budibase · error · HTTPError
Project id is required.
Error message
Project id is required.
What it means
update() requires the _id of the project being modified; calling it without _id throws this 400 HTTPError before any validation or DB access. The SDK expects a full UpdateProjectInput with identity fields present.
Source
Thrown at packages/server/src/sdk/workspace/projects/crud.ts:95
const now = new Date().toISOString()
const response = await db.put(
{
...project,
color: normaliseProjectColor(project.color),
_id: docIds.generateProjectID(),
createdAt: now,
updatedAt: now,
},
{ returnDoc: true }
)
return response.doc
}
export async function update(project: UpdateProjectInput): Promise<Project> {
if (!project._id) {
throw new HTTPError("Project id is required.", 400)
}
if (!project._rev) {
throw new HTTPError("Project revision is required.", 400)
}
if (Object.hasOwn(project, "name")) {
validateProjectName(project.name)
}
const db = context.getWorkspaceDB()
const persisted = await get(project._id)
if (!persisted) {
throw new HTTPError(`Project with id '${project._id}' not found.`, 404)
}
const response = await db.put(
{
...persisted,
...project,View on GitHub (pinned to a81a902e9a)
Solutions
- Populate _id from the persisted project before calling update
- Guard the call: if (!project._id) throw/return before invoking the SDK
- Verify the object you spread into the update payload actually contains _id
- Re-fetch the project (sdk.projects.get / fetch) to obtain its _id
Example fix
// before
await sdk.projects.update({ _rev: project._rev, name: "New" })
// after
await sdk.projects.update({ _id: project._id!, _rev: project._rev, name: "New" }) Defensive patterns
Strategy: type-guard
Validate before calling
const hasId = (p: { _id?: string }): p is { _id: string } =>
typeof p._id === "string" && p._id.length > 0
if (!hasId(payload)) throw new Error("Missing project _id")
await sdk.projects.update(payload) Type guard
const hasProjectId = (p: { _id?: string }): p is { _id: string } =>
typeof p._id === "string" && p._id.length > 0 Try / catch
try {
await sdk.projects.update(payload as { _id: string; _rev: string })
} catch (e) {
if (String(e.message).includes("id is required")) {
// re-fetch the project to recover its _id
}
} Prevention
- Always build update payloads from a fetched Project object
- Don't destructure _id from possibly-unhydrated list rows
- Let TypeScript strictness flag optional _id before calling update
When it happens
Trigger: sdk.projects.update({ _rev, name }) with _id undefined/null/empty — usually a destructuring bug, an optional-chained id that was undefined, or constructing the payload from a failed fetch.
Common situations: Client code reading project._id from a list row that was never hydrated; responses from another API shape lacking _id; TypeScript suppressed so an undefined id slipped through.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Project name is required.
- Project revision is required.
- Invalid bookmark query
- Invalid limit query
- Limit query must be between 1 and 100
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/ec616046c2b4a806.
Report an issue: GitHub.