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.

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)

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.