different-ai/openwork · error · RemoteMcpAppError

cached_app_digest_mismatch

cached_app_digest_mismatch

Error message

The cached app revision failed its integrity check.

What it means

activateRemoteMcpAppRevision verifies the cached revision's integrity: sha256(version.rawSourceText) must equal payload.resource.digest stored at import/refresh time. On mismatch it throws 422 cached_app_digest_mismatch and refuses activation, protecting against tampered or corrupted cached app source.

Source

Thrown at ee/apps/den-api/src/remote-mcp-apps.ts:559

  if (app.status === "retired") {
    throw new RemoteMcpAppError(409, "app_retired", "Restore this app before activating a revision.")
  }
  let versionId: DenTypeId<"configObjectVersion">
  try {
    versionId = normalizeDenTypeId("configObjectVersion", input.versionId)
  } catch {
    throw new RemoteMcpAppError(404, "app_revision_not_found", "App revision not found.")
  }
  const versions = await db.select().from(ConfigObjectVersionTable).where(and(
    eq(ConfigObjectVersionTable.configObjectId, app.configObjectId),
    eq(ConfigObjectVersionTable.id, versionId),
    eq(ConfigObjectVersionTable.isDeletedVersion, false),
  )).limit(1)
  const version = versions[0]
  if (!version || !version.rawSourceText) throw new RemoteMcpAppError(404, "app_revision_not_found", "App revision not found.")
  const payload = parseVersionPayload(version)
  if (sha256(version.rawSourceText) !== payload.resource.digest) {
    throw new RemoteMcpAppError(422, "cached_app_digest_mismatch", "The cached app revision failed its integrity check.")
  }
  const updatedAt = new Date()
  await db.update(RemoteMcpAppTable).set({ activeVersionId: versionId, status: "active", retiredAt: null, updatedAt })
    .where(eq(RemoteMcpAppTable.configObjectId, app.configObjectId))
  return serializeApp({ ...app, activeVersionId: versionId, status: "active", retiredAt: null, updatedAt }, "editor")
}

export async function setRemoteMcpAppRetired(input: {
  context: PluginArchActorContext
  configObjectId: string
  retired: boolean
}) {
  const app = await getAppRow(input.context, input.configObjectId, "manager")
  if (!input.retired) {
    if (!app.activeVersionId) {
      throw new RemoteMcpAppError(409, "app_has_no_active_revision", "Activate an app revision before restoring it.")
    }
    const updatedAt = new Date()

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Run refreshRemoteMcpApp to re-fetch and cache a fresh revision with a correct digest, then activate it.
  2. Delete and re-import the app (importRemoteMcpApp) if the cached revision is unusable.
  3. Confirm the sha256 implementation and payloadForFetchedApp digest computation are consistent across den-api versions.
  4. Check for unauthorized/manual modifications to the config_object_version row.
Defensive patterns

Strategy: try-catch

Try / catch

try { await activateRemoteMcpAppRevision({ context, configObjectId, versionId }) } catch (e) {
  if (e instanceof RemoteMcpAppError && e.code === 'cached_app_digest_mismatch') {
    // cached source is corrupt/tampered: refreshRemoteMcpApp to re-cache, then activate
  }
}

Prevention

When it happens

Trigger: Activating a revision where rawSourceText was edited/migrated/corrupted after caching, or the normalized payload's resource.digest was written with a different hashing input (schema/code change between write and verify).

Common situations: Manual DB edits to config_object_version rows; storage-layer corruption; a version written by an older den-api build whose digest algorithm or payload shape changed.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/f83af29adcb80c8c. Report an issue: GitHub.