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

  1. Verify the project id exists (GET the project or list projects) before deleting, using the same workspace context
  2. Treat a 404 as idempotent success if the goal is 'project is gone' and skip the delete
  3. Check that the request runs in the correct tenant/workspace context so getWorkspaceDB() resolves the right database
  4. 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

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


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/7283d8af2b750a35. Report an issue: GitHub.