Budibase/budibase · error

App not found

Error message

App not found

What it means

The recaptcha middleware resolves app metadata from the workspace cache before applying reCAPTCHA checks. If the cache returns an entry marked INVALID (the app doc cannot be resolved), it throws 'App not found' instead of continuing to the route handler.

Source

Thrown at packages/server/src/middleware/recaptcha.ts:29

  const workspaceId = context.getWorkspaceId()
  // no app ID, requests are not targeting an app
  // if not production app - this is in the builder, recaptcha isn't enabled
  if (!workspaceId || !isProdWorkspaceID(workspaceId)) {
    return next()
  }
  if (!(await features.isRecaptchaEnabled())) {
    return next()
  }
  // builder users can skip validation if request comes from the builder
  if (
    sdk.users.isBuilder(ctx.user) &&
    ctx.headers[Header.CLIENT] === ClientHeader.BUILDER
  ) {
    return next()
  }
  const app = await cache.workspace.getWorkspaceMetadata(workspaceId)
  if ("state" in app && app.state === cache.workspace.WorkspaceState.INVALID) {
    throw new Error("App not found")
  }
  if ((app as Workspace).features?.recaptchaEnabled) {
    const cookie = utils.getCookie<RecaptchaSessionCookie>(
      ctx,
      Cookie.RecaptchaSession
    )
    if (!cookie) {
      ctx.status = 498
      return
    }
    const verified = await isRecaptchaVerified(cookie.sessionId)
    if (!verified) {
      ctx.status = 498
      return
    }
  }
  return next()
}

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Confirm the appId/workspaceId in the request URL matches an existing app (check the app's doc in CouchDB).
  2. Republish or recreate the app if it was deleted.
  3. Clear the app metadata cache / restart services so invalid cache entries are re-fetched.
  4. Check proxy/ReverseProxy config so requests aren't routed with a stale app id.

Example fix

// before
curl https://host/app-id-that-was-deleted
// after
curl https://host/correct-app-id  (or republish the app first)
Defensive patterns

Strategy: try-catch

Validate before calling

const meta = await cache.workspace.getWorkspaceMetadata(workspaceId)
if ("state" in meta && meta.state === cache.workspace.WorkspaceState.INVALID) throw new Error("App not found")

Type guard

const isValidApp = (m: unknown): m is Workspace => typeof m === "object" && m !== null && !("state" in m && (m as any).state === "invalid")

Try / catch

try {
  await next()
} catch (e) {
  if (e.message === "App not found") {
    ctx.status = 404
    ctx.body = { message: "App not found" }
    return
  }
  throw e
}

Prevention

When it happens

Trigger: An HTTP request (not from the builder client) whose workspaceId/appId resolves to invalid or deleted app metadata in cache.workspace.getWorkspaceMetadata - e.g. requesting an app URL for an app that was deleted or whose DB is missing.

Common situations: Hitting a published app URL after the app was deleted; stale/misconfigured proxy routing to a nonexistent appId; dev environments where the CouchDB app database was wiped but DNS/URL still points at the old app id.

Related errors


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