{"record":{"id":"2b692142b26df219","repo":"paperclipai/paperclip","slug":"file-consent-requires-a-configured-tenant-and-app","errorCode":null,"errorMessage":"file-consent requires a configured tenant and App hook","messagePattern":"file-consent requires a configured tenant and App hook","errorType":"exception","errorClass":"TeamsAdapterCompatibilityError","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-sdk-runtime.ts","lineNumber":2221,"sourceCode":"      options.callbacks.onSlashCommand\n    ) {\n      installDiscordNativeCommands(\n        this.adapter,\n        this.chat,\n        options.providerConfig.credentials.applicationId,\n        options.providerConfig.credentials.guildId,\n        this.discordCommandDispatch,\n      );\n    }\n    if (this.teamsFileConsentEnabled) {\n      const app = (this.adapter as unknown as TeamsAdapterInternals).app;\n      if (\n        !app ||\n        typeof app.on !== \"function\" ||\n        !this.microsoftTeamsTenantId ||\n        options.providerConfig.provider !== \"microsoft-teams\"\n      ) {\n        throw new TeamsAdapterCompatibilityError(\n          \"file-consent requires a configured tenant and App hook\",\n        );\n      }\n      const callback = options.callbacks.onTeamsFileConsent!;\n      installTeamsFileConsentHook(app as TeamsConsentApp, {\n        companyId: this.companyId,\n        endpointId: this.endpointId,\n        tenantId: this.microsoftTeamsTenantId,\n        botAppId: options.providerConfig.credentials.appId,\n        onConsent: async (event) => {\n          const attempt = this.webhookIngress.getStore();\n          const promise = Promise.resolve().then(() =>\n            callback({\n              endpointId: this.endpointId,\n              provider: this.provider,\n              event,\n            }),\n          );","sourceCodeStart":2203,"sourceCodeEnd":2239,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-sdk-runtime.ts#L2203-L2239","documentation":"Installing the Teams file-consent hook requires three things: an app object with an .on() hook method, a configured Microsoft Teams tenant ID (this.microsoftTeamsTenantId), and the provider being 'microsoft-teams'. If any precondition fails, this TeamsAdapterCompatibilityError is thrown because file-consent flows cannot be wired without them.","triggerScenarios":"Enabling file-consent callbacks when: options.app is missing or lacks an on() function, this.microsoftTeamsTenantId is unset, or options.providerConfig.provider !== 'microsoft-teams'.","commonSituations":"MICROSOFT_TEAMS_TENANT_ID (or equivalent config) not set in the environment; file-consent enabled for a non-Teams provider; app object not yet initialized when hook installation runs; adapter instantiated before tenant configuration loads.","solutions":["Set the Microsoft Teams tenant ID in configuration/env before constructing the runtime.","Enable the file-consent option only for provider 'microsoft-teams'.","Pass the initialized Chat SDK app (with a working .on() method) into the runtime options.","Verify adapter initialization order: app must exist before onTeamsFileConsent hook installation."],"exampleFix":"// before\ninstallFileConsent({ providerConfig: { provider: \"telegram\" }, callbacks: { onTeamsFileConsent } }); // wrong provider\n// after\nif (options.providerConfig.provider === \"microsoft-teams\" && process.env.MICROSOFT_TEAMS_TENANT_ID) {\n  installFileConsent(options);\n}","handlingStrategy":"validation","validationCode":"const canInstallConsent = Boolean(app) && typeof app?.on === \"function\" &&\n  Boolean(microsoftTeamsTenantId) && providerConfig.provider === \"microsoft-teams\";\nif (!canInstallConsent) throw new Error(\"file-consent prerequisites missing\");","typeGuard":"function canInstallFileConsent(app: unknown, tenantId: string | undefined, provider: string): boolean {\n  return typeof app === \"object\" && app !== null && typeof (app as any).on === \"function\" &&\n    typeof tenantId === \"string\" && tenantId.length > 0 && provider === \"microsoft-teams\";\n}","tryCatchPattern":"try {\n  runtime.installFileConsentHook();\n} catch (err) {\n  if (err instanceof TeamsAdapterCompatibilityError && /file-consent/.test(err.message)) {\n    logger.error(\"file-consent skipped: set tenant ID and use the microsoft-teams provider\");\n    return;\n  }\n  throw err;\n}","preventionTips":["Set the Teams tenant ID env/config before runtime construction.","Only enable onTeamsFileConsent callbacks for microsoft-teams provider.","Verify app.on exists before enabling consent features."],"tags":["teams","file-consent","configuration"],"backgroundTag":"missing-required-config-field","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"}