Budibase/budibase · error

Unable to revert. ${err}

Error message

Unable to revert. ${err}

What it means

devRevertProcessor.revertApp performs a replication-based revert of a development app back to its production state, then emits a reverted event. Any failure inside the revert flow (db.put, metadata invalidation, replication errors) is caught and re-thrown wrapped in 'Unable to revert. <err>' with the original error as cause.

Source

Thrown at packages/server/src/sdk/dev/devRevertProcessor.ts:76

      source: productionAppId,
      target: appId,
    })

    try {
      await replication.rollback()

      // update appID in reverted app to be dev version again
      const db = context.getWorkspaceDB()
      const appDoc = await db.get<Workspace>(DocumentType.WORKSPACE_METADATA)
      appDoc.appId = appId
      appDoc.instance._id = appId
      await db.put(appDoc)
      await cache.workspace.invalidateWorkspaceMetadata(appId)
      await events.app.reverted(appDoc)

      return { message: "Reverted changes successfully." }
    } catch (err) {
      throw new Error(`Unable to revert. ${err}`, { cause: err })
    } finally {
      await replication.close()
    }
  }
}

export function devRevertProcessor(): DevRevertProcessor {
  if (!_devRevertProcessor) {
    _devRevertProcessor = new DevRevertProcessor()
  }
  return _devRevertProcessor
}

export async function revertDevChanges(data: DevRevertQueueData) {
  const processor = devRevertProcessor()
  const result = await processor.execute(data)
  return result
}

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Inspect err.cause (the wrapped original error) - it names the real failure (e.g. replication conflict).
  2. Check CouchDB replication conflict documents (_conflicts) in the dev app DB and resolve/delete them.
  3. Verify the production appDoc still exists; recreate/republish the app if it was removed.
  4. Retry the revert after resolving conflicts; if persistent, delete the dev app and create a fresh one from prod.

Example fix

// diagnosing
try { await sdk.dev.revertApp(appId) } catch (e) { console.log(e.cause) }
// resolution: resolve _conflicts in the dev DB, then retry the revert
Defensive patterns

Strategy: try-catch

Validate before calling

const prodDoc = await prodDb.get(appId).catch(() => null)
if (!prodDoc) throw new Error("Cannot revert: production app doc missing")

Type guard

const hasCause = (e: unknown): e is Error & { cause: Error } => e instanceof Error && e.cause instanceof Error

Try / catch

try {
  await sdk.dev.revertApp(appId)
} catch (e) {
  console.error("Revert failed:", e.cause ?? e)
  // resolve replication conflicts reported by e.cause before retrying
}

Prevention

When it happens

Trigger: Calling the revert app endpoint when replication from prod to dev fails: missing/locked dev appDoc, CouchDB replication conflicts, or appDoc put failures inside the try block.

Common situations: Developers clicking 'Revert changes' in the builder while the dev database has replication conflicts; the production app doc was deleted so the revert target no longer exists; CouchDB connection issues mid-replication.

Related errors


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