different-ai/openwork · error · RemoteMcpAppError

invalid_cached_app

invalid_cached_app

Error message

The cached app revision metadata is invalid.

What it means

parseVersionPayload validates the JSON payload stored in a remote MCP app version row. If normalizedPayloadJson is not a record, or its kind is not "remote_mcp_app", this 422 invalid_cached_app error is thrown: the cached revision metadata in the database is unreadable or was written by an incompatible writer.

Source

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

    source: {
      url: fetched.sourceUrl,
      resolvedUrl: fetched.resolvedSourceUrl,
      fetchedAt: fetched.fetchedAt,
      contentType: fetched.contentType,
    },
    resource: {
      byteSize: fetched.byteSize,
      digest: fetched.digest,
      csp: { connectDomains: [], resourceDomains: [], frameDomains: [], baseUriDomains: [] },
    },
    diagnostics: fetched.diagnostics,
  }
}

function parseVersionPayload(row: Pick<RemoteMcpAppVersionRow, "normalizedPayloadJson">): RemoteMcpAppVersionPayload {
  const value = row.normalizedPayloadJson
  if (!isRecord(value) || value.kind !== "remote_mcp_app") {
    throw new RemoteMcpAppError(422, "invalid_cached_app", "The cached app revision metadata is invalid.")
  }
  const metadata = remoteMcpAppDocumentMetadataSchema.safeParse(value.metadata)
  const source = isRecord(value.source) ? value.source : null
  const resource = isRecord(value.resource) ? value.resource : null
  if (!metadata.success || !source || !resource
    || typeof source.url !== "string" || typeof source.resolvedUrl !== "string" || typeof source.fetchedAt !== "string"
    || (source.contentType !== null && typeof source.contentType !== "string")
    || typeof resource.byteSize !== "number" || typeof resource.digest !== "string") {
    throw new RemoteMcpAppError(422, "invalid_cached_app", "The cached app revision metadata is invalid.")
  }
  return value as RemoteMcpAppVersionPayload
}

async function getAppRow(context: PluginArchActorContext, configObjectId: string, role: "viewer" | "editor" | "manager" = "viewer") {
  let id: DenTypeId<"configObject">
  try {
    id = normalizeDenTypeId("configObject", configObjectId)
  } catch {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Delete/re-import the affected app so the revision payload is regenerated from the source URL.
  2. Restore the row's normalizedPayloadJson from a backup taken before the corruption.
  3. Run the pending den-api migrations that backfill payload kind/metadata.
  4. Check the den-api version that wrote the row matches the version reading it.
Defensive patterns

Strategy: try-catch

Type guard

function isValidAppPayload(v: unknown): boolean {
  return typeof v === "object" && v !== null && (v as Record<string, unknown>).kind === "remote_mcp_app";
}

Try / catch

try {
  const revision = await getRemoteMcpAppRevision(context, configObjectId);
} catch (e) {
  if (e instanceof RemoteMcpAppError && e.code === "invalid_cached_app") {
    // cache is corrupt; re-import the app from its source URL
  } else throw e;
}

Prevention

When it happens

Trigger: Reading an app version row (via serializeRevision/payload callers) whose normalizedPayloadJson column is null, malformed, or has kind != "remote_mcp_app" — e.g. rows written by an older schema version or corrupted by a failed migration.

Common situations: Manual DB edits or partial migrations leaving rows without the payload envelope; a version upgrade changing the payload shape; importing/copying rows between environments with different payload formats.

Related errors


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