different-ai/openwork · error · RemoteMcpAppError

app_import_incomplete

app_import_incomplete

Error message

The immutable app revision was not created.

What it means

importRemoteMcpApp downloads a remote MCP app, creates a plugin, a config object, and an initial immutable config-object version. If createConfigObject returns without a latestVersion.id, the code cannot record an immutable revision to activate, so it throws 422 app_import_incomplete before inserting the RemoteMcpAppTable row. It guards against importing an app that has no persisted revision behind it.

Solutions

  1. Verify createConfigObject is returning an object that includes latestVersion.id for sourceMode 'import'; check the config-object service logs for failed version writes.
  2. Retry the import with a fresh call to importRemoteMcpApp; no app row is inserted when this throws, so retrying is safe.
  3. Confirm the fetched payload (payloadForFetchedApp output, rawSourceText, schemaVersion) passes config-object validation so the initial version is materialized.
  4. If it persists, upgrade/patch the den-api config-object service so an 'app' object always gets an initial version.

Example fix

// no caller code change; ensure import payload is valid
await importRemoteMcpApp({ context, sourceUrl, pluginId, activate: true })
// on 422, retry after fixing the server-side version materialization
Defensive patterns

Strategy: retry

Try / catch

try { await importRemoteMcpApp(input) } catch (e) {
  if (e instanceof RemoteMcpAppError && e.code === 'app_import_incomplete') {
    // no app row was inserted; safe to retry after checking server version-write health
  }
}

Prevention

When it happens

Trigger: Calling importRemoteMcpApp where createConfigObject (objectType 'app', sourceMode 'import') succeeds but configObject.latestVersion?.id is undefined — e.g. the config-object service created the object but did not materialize an initial version for the provided normalizedPayloadJson/rawSourceText payload.

Common situations: Importing a remote MCP app from a URL whose payload the version-writing path silently skipped; a backend/regression where createConfigObject stops returning latestVersion; partial transactional failure between object creation and version creation.

Related errors


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

Appendix: source

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

      description: fetched.metadata.description,
      sourceRepositoryUrl: fetched.sourceUrl.length <= 1024 ? fetched.sourceUrl : null,
    })
    pluginId = normalizeDenTypeId("plugin", plugin.id)
  }
  const configObject = await createConfigObject({
    context: input.context,
    objectType: "app",
    pluginIds: [pluginId],
    requireFreshSession: input.requireFreshSession,
    sourceMode: "import",
    value: {
      normalizedPayloadJson: payloadForFetchedApp(fetched) as unknown as Record<string, unknown>,
      rawSourceText: fetched.html,
      schemaVersion: REMOTE_MCP_APP_CONFIG_SCHEMA_VERSION,
    },
  })
  const versionId = configObject.latestVersion?.id
  if (!versionId) throw new RemoteMcpAppError(422, "app_import_incomplete", "The immutable app revision was not created.")
  const now = new Date()
  const app: RemoteMcpAppRow = {
    configObjectId: normalizeDenTypeId("configObject", configObject.id),
    organizationId: input.context.organizationContext.organization.id,
    pluginId,
    activeVersionId: input.activate === false ? null : normalizeDenTypeId("configObjectVersion", versionId),
    sourceUrl: fetched.sourceUrl,
    resolvedSourceUrl: fetched.resolvedSourceUrl,
    status: "active",
    createdAt: now,
    updatedAt: now,
    retiredAt: null,
  }
  await db.insert(RemoteMcpAppTable).values(app)
  return serializeApp(app, "manager")
}

export async function getRemoteMcpApp(input: { context: PluginArchActorContext; configObjectId: string }) {

View on GitHub (pinned to 2b7df46e8a)