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
- Upgrade the microsoft-teams adapter to a version implementing paperclipRecordAcceptedActivity.
- Feature-detect both recorders before calling recordMicrosoftTeamsRoute whenever a raw activity will be passed, or omit the raw argument.
- 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
- Upgrade the Teams adapter so both recorders ship together.
- Feature-detect both paperclipRecordThreadServiceUrl and paperclipRecordAcceptedActivity before passing raw.
- Note the partial-write hazard: the route is stored before this throw; retry without raw to reconcile.
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
- durable route recorder is unavailable
- file publication receipt capture is unavailable
- file publication receipt lookup is unavailable
- file-consent runtime is not enabled
- ensureRootThread is unavailable
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/64a4e0654c1388ff.
Report an issue: GitHub.