{"record":{"id":"91f955afdb7ecae5","repo":"paperclipai/paperclip","slug":"cacheusercontext-is-unavailable","errorCode":null,"errorMessage":"cacheUserContext is unavailable","messagePattern":"cacheUserContext is unavailable","errorType":"exception","errorClass":"TeamsAdapterCompatibilityError","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-sdk-runtime.ts","lineNumber":1022,"sourceCode":" * forcing unrelated Teams threads through a single network queue.\n */\nexport function scopeMicrosoftTeamsEgress(\n  adapter: Adapter,\n  configuredApiUrl?: string,\n  enableFileConsent = false,\n): Adapter {\n  const teams = adapter as unknown as TeamsAdapterInternals;\n  if (!teams.app?.api) {\n    throw new TeamsAdapterCompatibilityError(\"app.api is unavailable\");\n  }\n  if (typeof teams.decodeThreadId !== \"function\") {\n    throw new TeamsAdapterCompatibilityError(\"decodeThreadId is unavailable\");\n  }\n  if (typeof teams.openDM !== \"function\") {\n    throw new TeamsAdapterCompatibilityError(\"openDM is unavailable\");\n  }\n  if (typeof teams.cacheUserContext !== \"function\") {\n    throw new TeamsAdapterCompatibilityError(\"cacheUserContext is unavailable\");\n  }\n  if (typeof teams.getIncomingUser !== \"function\") {\n    throw new TeamsAdapterCompatibilityError(\"getIncomingUser is unavailable\");\n  }\n  if (typeof teams.getUser !== \"function\") {\n    throw new TeamsAdapterCompatibilityError(\"getUser is unavailable\");\n  }\n  for (const methodName of TEAMS_THREAD_SCOPED_METHODS) {\n    if (typeof teams[methodName] !== \"function\") {\n      throw new TeamsAdapterCompatibilityError(`${methodName} is unavailable`);\n    }\n  }\n  if (\n    typeof teams.app.api.constructor !== \"function\" ||\n    !(\"http\" in teams.app.api)\n  ) {\n    throw new TeamsAdapterCompatibilityError(\n      \"the API client constructor or HTTP transport is unavailable\",","sourceCodeStart":1004,"sourceCodeEnd":1040,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-sdk-runtime.ts#L1004-L1040","documentation":"Continuing the same compatibility gate, the runtime requires adapter.cacheUserContext to be a function; when absent it throws TeamsAdapterCompatibilityError('cacheUserContext is unavailable'). Without it the runtime cannot persist Teams user context across turns and refuses to wire the adapter.","triggerScenarios":"Providing a Teams adapter whose internals have app.api, decodeThreadId, and openDM but lack a cacheUserContext function — typically a version mismatch or an incomplete stub, since the checks run sequentially and this one fails only after the earlier methods passed.","commonSituations":"Partially upgraded adapter package where some methods were added in one release and others in a later one; custom adapter covering the thread/DM APIs but not user-context caching; mocks extended only as far as the previous failure.","solutions":["Bring the Teams adapter package to the version the runtime expects (all required internals present).","Implement cacheUserContext on the custom adapter with the expected signature.","Add cacheUserContext: vi.fn() to test doubles.","After fixing, re-run so the gate proceeds to the remaining checks (getIncomingUser, getUser)."],"exampleFix":"// before\nconst adapter = { app: { api: {} }, decodeThreadId: vi.fn(), openDM: vi.fn() };\n// after\nconst adapter = { app: { api: {} }, decodeThreadId: vi.fn(), openDM: vi.fn(), cacheUserContext: vi.fn() };","handlingStrategy":"type-guard","validationCode":"const teams = adapter as unknown as TeamsAdapterInternals;\nif (typeof teams.cacheUserContext !== \"function\") throw new Error(\"adapter missing cacheUserContext\");","typeGuard":"function supportsCacheUserContext(a: unknown): a is TeamsAdapterInternals {\n  return typeof (a as TeamsAdapterInternals)?.cacheUserContext === \"function\";\n}","tryCatchPattern":"try {\n  wireTeamsAdapter(adapter);\n} catch (e) {\n  if (e instanceof TeamsAdapterCompatibilityError && e.message.includes(\"cacheUserContext\")) {\n    // implement/upgrade so cacheUserContext exists\n  }\n}","preventionTips":["Run the full compatibility gate in a smoke test at CI time for every adapter version bump.","Implement the entire internal contract (app.api, decodeThreadId, openDM, cacheUserContext, getIncomingUser, getUser) in custom adapters.","Complete stubs iteratively: after fixing one missing method, re-run to catch the next.","Keep adapter and runtime packages upgraded together in the same change."],"tags":["teams","adapter-compatibility","api-contract"],"backgroundTag":"method-not-implemented","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}