paperclipai/paperclip · error · TeamsAdapterCompatibilityError

durable route recorder is unavailable

Error message

durable route recorder is unavailable

What it means

recordMicrosoftTeamsRoute persists the authenticated Bot Connector serviceUrl for a Teams thread using the adapter's internal paperclipRecordThreadServiceUrl hook. For non-Teams providers it is a no-op (early return), but when the provider IS microsoft-teams and the adapter lacks the recorder function, the runtime cannot durably store the route and throws a TeamsAdapterCompatibilityError.

Source

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

  }

  /**
   * Persist a Teams activity's authenticated reply route only after the
   * control plane has accepted the callback under the current runtime and
   * credential generation. The route is intentionally separate from the
   * durable provider thread id because Microsoft can move a conversation
   * between regional Bot Connector service URLs.
   */
  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>,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Upgrade the microsoft-teams adapter so it implements paperclipRecordThreadServiceUrl.
  2. Feature-detect the recorder before calling and skip durable route persistence (log a warning) when absent.
  3. Align adapter and chat-sdk-runtime versions so the internal contract matches.

Example fix

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

// after
const teams = runtime.getProviderAdapter() as {
  paperclipRecordThreadServiceUrl?: unknown;
};
if (typeof teams.paperclipRecordThreadServiceUrl === "function") {
  await runtime.recordMicrosoftTeamsRoute(threadId, serviceUrl, raw);
} else {
  console.warn("teams durable route recorder unavailable; skipping persistence");
}
Defensive patterns

Strategy: type-guard

Validate before calling

const teams = runtime.getProviderAdapter() as Record<string, unknown>;
if (runtime.provider === "microsoft-teams" && typeof teams.paperclipRecordThreadServiceUrl !== "function") {
  console.warn("teams adapter lacks durable route recorder");
}

Type guard

function supportsRouteRecording(a: unknown): a is { paperclipRecordThreadServiceUrl: (threadId: string, serviceUrl: unknown) => Promise<void> } {
  return typeof a === "object" && a !== null && typeof (a as any).paperclipRecordThreadServiceUrl === "function";
}

Try / catch

try {
  await runtime.recordMicrosoftTeamsRoute(threadId, serviceUrl, raw);
} catch (err) {
  if (err instanceof TeamsAdapterCompatibilityError && err.message.includes("route recorder is unavailable")) {
    console.warn("skipping durable route persistence");
  } else throw err;
}

Prevention

When it happens

Trigger: A Teams activity callback invoking recordMicrosoftTeamsRoute(threadId, serviceUrl, raw) where the wired microsoft-teams adapter does not define paperclipRecordThreadServiceUrl — e.g. an older adapter build or a minimal test adapter.

Common situations: Teams adapter version pinned before the durable-routing feature; custom or stub Teams adapters missing paperclip* internals; dependency upgrade that swapped the adapter implementation without updating the runtime expectations.

Related errors


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