paperclipai/paperclip · error · TeamsAdapterCompatibilityError
durable route state is unavailable
Error message
durable route state is unavailable
What it means
To durably persist a Teams conversation route, the runtime needs the adapter's chat state store (teams.chat.getState()). If the state client is not available — because durable state storage was never configured for the Teams adapter — this TeamsAdapterCompatibilityError is thrown instead of silently dropping the route.
Source
Thrown at server/src/services/chat-sdk-runtime.ts:1298
}
teams.paperclipRecordThreadServiceUrl = async (
threadId: string,
serviceUrlValue: unknown,
) => {
const decoded = teams.decodeThreadId!(threadId);
if (typeof decoded.conversationId !== "string" || !decoded.conversationId) {
throw new TeamsServiceUrlValidationError(
"Teams destination is missing its conversation identity",
);
}
const serviceUrl = trustedTeamsServiceUrl(
serviceUrlValue,
trustedConfiguredApiUrl,
);
const state = teams.chat?.getState();
if (!state) {
throw new TeamsAdapterCompatibilityError(
"durable route state is unavailable",
);
}
await state.set(
teamsConversationRouteStateKey(decoded.conversationId),
serviceUrl,
);
};
for (const methodName of TEAMS_THREAD_SCOPED_METHODS) {
const original = teams[methodName];
if (typeof original !== "function") continue;
teams[methodName] = (threadId: string, ...args: unknown[]) =>
withThreadServiceUrl(threadId, async () =>
Reflect.apply(original, teams, [threadId, ...args]),
);
}
const originalOpenDM = teams.openDM;View on GitHub (pinned to 01ad858492)
Solutions
- Configure durable state storage for the Teams adapter (e.g. blob or file-backed state) so teams.chat.getState() returns a store.
- Confirm the adapter was initialized (chat.initialize()) before recording routes.
- Check adapter construction options: ensure the Chat state plugin/middleware is enabled for microsoft-teams.
- If durability is intentionally disabled, bypass paperclipRecordThreadServiceUrl and rely on serviceUrl embedded in incoming activities.
Example fix
// before
new TeamsAdapter({ /* no state configured */ });
// after
new TeamsAdapter({ chat: { state: new FileStateStore("./data/teams-state") } }); Defensive patterns
Strategy: validation
Validate before calling
const state = teams.chat?.getState();
if (!state) throw new Error("configure durable state storage before recording Teams routes"); Type guard
null
Try / catch
try {
await teams.paperclipRecordThreadServiceUrl(threadId, serviceUrl);
} catch (err) {
if (err instanceof TeamsAdapterCompatibilityError && /route state/.test(err.message)) {
logger.error("Teams durable state store not configured; routes will not persist");
return; // fall back to serviceUrl from incoming activities
}
throw err;
} Prevention
- Always configure a state store (blob/file/memory) for the Teams adapter in production.
- Await chat.initialize() before any route persistence.
- Add a startup smoke check that getState() returns a store.
When it happens
Trigger: Calling teams.paperclipRecordThreadServiceUrl when teams.chat is undefined or teams.chat.getState() returns null/undefined, i.e. the Teams adapter was constructed without a durable state store.
Common situations: Running without configured state storage (e.g. no blob/file/memory state configured in the bot adapter); production adapter built without Chat state middleware; misconfigured adapter options that disable state; SDK version where getState is lazily unavailable until initialize.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- durable accepted-activity state is unavailable
- file-consent requires a configured tenant and App hook
- OpenCode evals require exact version 1.18.17; received ${ver
- devUiUrl must use http or https protocol
- devUiUrl must target localhost
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/11153712203974cf.
Report an issue: GitHub.