{"record":{"id":"20a3911581b0403d","repo":"different-ai/openwork","slug":"app-has-no-active-revision","errorCode":"app_has_no_active_revision","errorMessage":"Activate an app revision before caching an update.","messagePattern":"Activate an app revision before caching an update\\.","errorType":"http","errorClass":"RemoteMcpAppError","httpStatus":409,"severity":"error","filePath":"ee/apps/den-api/src/remote-mcp-apps.ts","lineNumber":507,"sourceCode":"  }\n  await db.insert(RemoteMcpAppTable).values(app)\n  return serializeApp(app, \"manager\")\n}\n\nexport async function getRemoteMcpApp(input: { context: PluginArchActorContext; configObjectId: string }) {\n  const app = await getAppRow(input.context, input.configObjectId)\n  const role = await resolvePluginArchResourceRole({ context: input.context, resourceId: app.configObjectId, resourceKind: \"config_object\" })\n  if (!role) throw new RemoteMcpAppError(404, \"remote_app_not_found\", \"Remote MCP App not found.\")\n  return serializeApp(app, role)\n}\n\nexport async function refreshRemoteMcpApp(input: {\n  context: PluginArchActorContext\n  configObjectId: string\n  sourceUrl?: string\n}) {\n  const app = await getAppRow(input.context, input.configObjectId, \"editor\")\n  if (!app.activeVersionId) throw new RemoteMcpAppError(409, \"app_has_no_active_revision\", \"Activate an app revision before caching an update.\")\n  const activeVersions = await db.select().from(ConfigObjectVersionTable).where(and(\n    eq(ConfigObjectVersionTable.configObjectId, app.configObjectId),\n    eq(ConfigObjectVersionTable.id, app.activeVersionId),\n    eq(ConfigObjectVersionTable.isDeletedVersion, false),\n  )).limit(1)\n  if (!activeVersions[0]) throw new RemoteMcpAppError(404, \"app_revision_not_found\", \"The active app revision was not found.\")\n  const fetched = await fetchRemoteMcpApp(input.sourceUrl ?? app.sourceUrl)\n  await createConfigObjectVersion({\n    context: input.context,\n    configObjectId: app.configObjectId,\n    reason: fetched.digest,\n    value: {\n      normalizedPayloadJson: payloadForFetchedApp(fetched) as unknown as Record<string, unknown>,\n      rawSourceText: fetched.html,\n      schemaVersion: REMOTE_MCP_APP_CONFIG_SCHEMA_VERSION,\n    },\n  })\n  const updatedAt = new Date()","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/remote-mcp-apps.ts#L489-L525","documentation":"refreshRemoteMcpApp caches a new revision from the remote source, but that only makes sense when the app has an active revision baseline. If app.activeVersionId is null (imported with activate:false or never activated), it throws 409 app_has_no_active_revision before any fetch or version write.","triggerScenarios":"Calling refreshRemoteMcpApp on an app whose activeVersionId is null — typically an app imported with activate:false that has never had a revision activated, or whose active revision was never set.","commonSituations":"Automated refresh jobs running over apps imported in deactivated mode; refreshing right after import when activation was deferred.","solutions":["Activate a revision first via activateRemoteMcpAppRevision with a valid versionId, then refresh.","If you intended the app active, re-import without activate:false so an active revision is set at import time.","Skip null-active apps in refresh loops or treat them as pending activation."],"exampleFix":"// before\nawait refreshRemoteMcpApp({ context, configObjectId })\n// after\nconst app = await getRemoteMcpApp({ context, configObjectId })\nif (!app.activeVersionId) {\n  await activateRemoteMcpAppRevision({ context, configObjectId, versionId: firstVersionId })\n}\nawait refreshRemoteMcpApp({ context, configObjectId })","handlingStrategy":"validation","validationCode":"const app = await getRemoteMcpApp({ context, configObjectId })\nif (!app.activeVersionId) throw new Error('Activate a revision before refreshing')","typeGuard":"function canRefresh(app: { activeVersionId: string | null }): app is { activeVersionId: string } {\n  return app.activeVersionId !== null\n}","tryCatchPattern":"try { await refreshRemoteMcpApp({ context, configObjectId }) } catch (e) {\n  if (e instanceof RemoteMcpAppError && e.code === 'app_has_no_active_revision') {\n    // activate a revision first, then retry refresh\n  }\n}","preventionTips":["Import apps with activate:true unless activation is intentionally deferred","Track apps pending activation and exclude them from refresh jobs","After import, verify activeVersionId is set before scheduling refreshes"],"tags":["state-conflict","http-409","activation"],"backgroundTag":"missing-active-revision","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}