Budibase/budibase · error · HTTPError
Project with id '${id}' not found.
Error message
Project with id '${id}' not found. What it means
This 404 HTTPError is thrown by the project (app) removal SDK function when the workspace database lookup for the given project id returns nothing. It means the caller asked to delete a project that does not exist in the current workspace DB, so the delete is aborted before any cascade work (assignments clearing, doc removal) runs.
Source
Thrown at packages/server/src/sdk/workspace/projects/crud.ts:250
rollbacks.push(async () => {
await db.put({ ...original, _rev: result.rev })
})
}
} catch (err) {
if (!(err instanceof HTTPError)) {
await rollbackAssignments(rollbacks)
}
throw err
}
return rollbacks
}
export async function remove(id: string, rev: string) {
const db = context.getWorkspaceDB()
const project = await get(id)
if (!project) {
throw new HTTPError(`Project with id '${id}' not found.`, 404)
}
if (project._rev !== rev) {
throw new HTTPError("Project revision does not match.", 409)
}
const rollbacks = await clearAssignments(id)
try {
return await db.remove(id, rev)
} catch (err) {
await rollbackAssignments(rollbacks)
throw err
}
}
View on GitHub (pinned to a81a902e9a)
Solutions
- Verify the project id exists (GET the project or list projects) before deleting, using the same workspace context
- Treat a 404 as idempotent success if the goal is 'project is gone' and skip the delete
- Check that the request runs in the correct tenant/workspace context so getWorkspaceDB() resolves the right database
- Confirm the id format matches what the API returned originally (no truncation, no URL-encoding issues)
Example fix
// before
await projects.remove(id, rev)
// after
const project = await projects.get(id)
if (project) {
await projects.remove(id, project._rev!)
} Defensive patterns
Strategy: try-catch
Validate before calling
const project = await projects.get(id)
if (!project) throw new Error(`Project ${id} does not exist; skip delete`) Type guard
function isProject(p: unknown): p is Project return !!p && typeof p === "object" && "_id" in p && "_rev" in p
Try / catch
try {
await projects.remove(id, rev)
} catch (e) {
if (e?.status === 404) return // already gone: treat as idempotent success
throw e
} Prevention
- Re-fetch the project immediately before delete to confirm existence and get a fresh rev
- Guard delete buttons against double submission
- Never hard-code project ids; always use ids returned by the API in the same tenant
- Log the workspace/tenant context with delete attempts to catch context mismatches
When it happens
Trigger: Calling remove(id, rev) where `get(id)` returns null/undefined: the id was already deleted, the id is malformed or belongs to another workspace/tenant, or a race where another request deleted the project first.
Common situations: Double-clicking a delete button and re-submitting the same DELETE request; stale UI listing a project deleted elsewhere; hardcoded/copy-pasted app ids across environments; tenant mismatch where the request context points at a different workspace DB.
Related errors
- Knowledge base file not found
- Error getting account by tenantId ${tenantId}
- DB does not exist
- ${err.message}
- CouchDB error: ${err.message}
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/7283d8af2b750a35.
Report an issue: GitHub.