paperclipai/paperclip · error · TeamsAdapterCompatibilityError

durable accepted-activity recorder is unavailable

Error message

durable accepted-activity recorder is unavailable

What it means

When recordMicrosoftTeamsRoute receives a raw activity, it additionally persists the accepted activity via teams.paperclipRecordAcceptedActivity. If the adapter implements the route recorder but not the accepted-activity recorder, the route is saved first and then the runtime throws TeamsAdapterCompatibilityError, leaving the durable route written without its paired accepted-activity record.

Source

Thrown at server/src/services/chat-sdk-runtime.ts:2554

   */
  async recordMicrosoftTeamsRoute(
    threadId: string,
    serviceUrl: unknown,
    raw?: unknown,
  ): Promise<void> {
    if (this.provider !== "microsoft-teams") return;
    const teams = this.adapter as unknown as TeamsAdapterInternals;
    const recorder = teams.paperclipRecordThreadServiceUrl;
    if (typeof recorder !== "function") {
      throw new TeamsAdapterCompatibilityError(
        "durable route recorder is unavailable",
      );
    }
    await recorder.call(this.adapter, threadId, serviceUrl);
    if (raw !== undefined) {
      const acceptedActivityRecorder = teams.paperclipRecordAcceptedActivity;
      if (typeof acceptedActivityRecorder !== "function") {
        throw new TeamsAdapterCompatibilityError(
          "durable accepted-activity recorder is unavailable",
        );
      }
      await acceptedActivityRecorder.call(this.adapter, raw);
    }
  }

  async sendTeamsFileConsentCard(
    threadId: string,
    card: ReturnType<typeof buildTeamsFileConsentCard>,
  ): Promise<{ id: string }> {
    return await this.sendTeamsFileCard(threadId, "consent", card);
  }

  async sendTeamsUploadedFileCard(
    threadId: string,
    card: ReturnType<typeof buildTeamsUploadedFileCard>,
  ): Promise<{ id: string }> {

View on GitHub (pinned to 01ad858492)

Solutions

  1. Upgrade the microsoft-teams adapter to a version implementing paperclipRecordAcceptedActivity.
  2. Feature-detect both recorders before calling recordMicrosoftTeamsRoute whenever a raw activity will be passed, or omit the raw argument.
  3. Reconcile durable state after this error: the serviceUrl was already persisted, so re-running with raw undefined avoids duplicate route writes.

Example fix

// before
await runtime.recordMicrosoftTeamsRoute(threadId, serviceUrl, raw);

// after
const teams = runtime.getProviderAdapter() as {
  paperclipRecordAcceptedActivity?: unknown;
};
await runtime.recordMicrosoftTeamsRoute(
  threadId,
  serviceUrl,
  typeof teams.paperclipRecordAcceptedActivity === "function" ? raw : undefined,
);
Defensive patterns

Strategy: type-guard

Validate before calling

const teams = runtime.getProviderAdapter() as Record<string, unknown>;
if (raw !== undefined && typeof teams.paperclipRecordAcceptedActivity !== "function") {
  raw = undefined; // persist route only, skip accepted-activity recording
}

Type guard

function supportsAcceptedActivityRecording(a: unknown): a is { paperclipRecordAcceptedActivity: (raw: unknown) => Promise<void> } {
  return typeof a === "object" && a !== null && typeof (a as any).paperclipRecordAcceptedActivity === "function";
}

Try / catch

try {
  await runtime.recordMicrosoftTeamsRoute(threadId, serviceUrl, raw);
} catch (err) {
  if (err instanceof TeamsAdapterCompatibilityError && err.message.includes("accepted-activity recorder is unavailable")) {
    await runtime.recordMicrosoftTeamsRoute(threadId, serviceUrl); // route already stored; finish without raw
  } else throw err;
}

Prevention

When it happens

Trigger: Calling recordMicrosoftTeamsRoute(threadId, serviceUrl, raw) with raw !== undefined on a microsoft-teams adapter that defines paperclipRecordThreadServiceUrl but omits paperclipRecordAcceptedActivity.

Common situations: Partially upgraded adapter that gained route recording in one release and accepted-activity recording in a later one; custom Teams adapters copying only part of the internal contract; test doubles implementing the route recorder only.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/64a4e0654c1388ff. Report an issue: GitHub.