{"record":{"id":"b8bb12158333918b","repo":"RocketChat/Rocket.Chat","slug":"cloud-connectivity-is-disabled-by-the-offline-lice","errorCode":null,"errorMessage":"Cloud connectivity is disabled by the offline license applied to this workspace","messagePattern":"Cloud connectivity is disabled by the offline license applied to this workspace","errorType":"exception","errorClass":"CloudOfflineLicenseError","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/cloud/offlineLicense.ts","lineNumber":11,"sourceCode":"import { License } from '@rocket.chat/license';\n\nimport { CloudOfflineLicenseError } from '../../../lib/errors/CloudOfflineLicenseError';\n\n/**\n * Guard for interactive cloud flows (registration, OAuth, billing). Background\n * jobs should instead skip silently by checking {@link License.hasOfflineLicense}.\n */\nexport function assertNotOfflineLicense(): void {\n\tif (License.hasOfflineLicense()) {\n\t\tthrow new CloudOfflineLicenseError('Cloud connectivity is disabled by the offline license applied to this workspace');\n\t}\n}\n","sourceCodeStart":1,"sourceCodeEnd":14,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/cloud/offlineLicense.ts#L1-L14","documentation":"assertNotOfflineLicense() guards every interactive cloud flow (registration, OAuth, billing): when the workspace runs under an offline/air-gapped license (License.hasOfflineLicense() === true), it throws CloudOfflineLicenseError. The license itself forbids cloud connectivity; background jobs are expected to check the flag themselves and skip silently instead of calling this guard.","triggerScenarios":"Any attempt to run cloud:connectWorkspace, finishOAuthAuthorization, or other guarded cloud flows on a workspace whose applied license is an offline license.","commonSituations":"Air-gapped enterprise deployments with an offline license; admin tooling or scripts calling cloud methods although the deployment is deliberately offline; setup wizard flows invoked by mistake on such installs.","solutions":["Do not offer or invoke cloud flows on offline-licensed workspaces — disable or hide the registration UI paths.","If cloud connectivity is actually required, apply a license that permits it instead of the offline license.","In background jobs, branch on License.hasOfflineLicense() and skip cloud calls silently."],"exampleFix":"// before\nawait finishOAuthAuthorization(code, state);\n\n// after\nimport { License } from '@rocket.chat/license';\nif (!License.hasOfflineLicense()) {\n  await finishOAuthAuthorization(code, state);\n}","handlingStrategy":"type-guard","validationCode":"import { License } from '@rocket.chat/license';\n\nif (License.hasOfflineLicense()) {\n  // offline-licensed workspace: skip cloud flows instead of calling them\n  return;\n}\nawait Meteor.callAsync('cloud:connectWorkspace', token);","typeGuard":"const cloudFlowsAllowed = (): boolean => !License.hasOfflineLicense();","tryCatchPattern":"import { CloudOfflineLicenseError } from '<lib/errors>';\n\ntry {\n  await finishOAuthAuthorization(code, state);\n} catch (e) {\n  if (e instanceof CloudOfflineLicenseError) {\n    // expected on offline deployments: hide cloud UI and skip — no retry will help\n  }\n  throw e;\n}","preventionTips":["Gate all cloud-related UI and scripts behind License.hasOfflineLicense() so the guard is never hit in production.","Use assertNotOfflineLicense only for interactive flows; background jobs should check the flag and skip silently.","Document which license types disable cloud connectivity so admins pick licenses matching their deployment."],"tags":["license","offline","air-gapped","cloud","rocket-chat"],"backgroundTag":"license-restriction","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}