different-ai/openwork · error · RemoteMcpAppError

app_retired

app_retired

Error message

Restore this app before activating a revision.

What it means

activateRemoteMcpAppRevision refuses to operate on retired apps. If app.status === 'retired', activating a revision is rejected with 409 app_retired; the app must first be restored (setRemoteMcpAppRetired with retired:false). This keeps retirement a blocking state.

Source

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

  })
  const updatedAt = new Date()
  await db.update(RemoteMcpAppTable).set({
    sourceUrl: fetched.sourceUrl,
    resolvedSourceUrl: fetched.resolvedSourceUrl,
    updatedAt,
  }).where(eq(RemoteMcpAppTable.configObjectId, app.configObjectId))
  const updated = { ...app, sourceUrl: fetched.sourceUrl, resolvedSourceUrl: fetched.resolvedSourceUrl, updatedAt }
  return serializeApp(updated, "editor")
}

export async function activateRemoteMcpAppRevision(input: {
  context: PluginArchActorContext
  configObjectId: string
  versionId: string
}) {
  const app = await getAppRow(input.context, input.configObjectId, "editor")
  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.")
  }

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Restore the app first: setRemoteMcpAppRetired({ context, configObjectId, retired: false }) with manager role.
  2. Then call activateRemoteMcpAppRevision with the desired versionId.
  3. If the app should stay retired, do not schedule activation work for it.

Example fix

// before
await activateRemoteMcpAppRevision({ context, configObjectId, versionId })
// after
await setRemoteMcpAppRetired({ context, configObjectId, retired: false })
await activateRemoteMcpAppRevision({ context, configObjectId, versionId })
Defensive patterns

Strategy: validation

Validate before calling

const app = await getRemoteMcpApp({ context, configObjectId })
if (app.status === 'retired') throw new Error('Restore the app before activating a revision')

Type guard

function isActivatable(app: { status: string }): boolean {
  return app.status !== 'retired'
}

Try / catch

try { await activateRemoteMcpAppRevision({ context, configObjectId, versionId }) } catch (e) {
  if (e instanceof RemoteMcpAppError && e.code === 'app_retired') {
    await setRemoteMcpAppRetired({ context, configObjectId, retired: false })
    // then retry activation
  }
}

Prevention

When it happens

Trigger: Calling activateRemoteMcpAppRevision for an app whose RemoteMcpAppTable.status is 'retired' (previously retired via setRemoteMcpAppRetired({retired:true})).

Common situations: Retrying an activation script after the app was retired; CI pipelines activating revisions on apps decommissioned by an admin.

Related errors


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