{"record":{"id":"5484a8e5682a1f9d","repo":"bitwarden/server","slug":"unable-to-get-cloud-billing-sync-connection","errorCode":null,"errorMessage":"Unable to get Cloud Billing Sync connection","messagePattern":"Unable to get Cloud Billing Sync connection","errorType":"exception","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"src/Api/Controllers/SelfHosted/SelfHostedOrganizationLicensesController.cs","lineNumber":121,"sourceCode":"    public async Task SyncLicenseAsync(string id)\n    {\n        var selfHostedOrganizationDetails = await _organizationRepository.GetSelfHostedOrganizationDetailsById(new Guid(id));\n        if (selfHostedOrganizationDetails == null)\n        {\n            throw new NotFoundException();\n        }\n\n        if (!await _currentContext.OrganizationOwner(selfHostedOrganizationDetails.Id))\n        {\n            throw new NotFoundException();\n        }\n\n        var billingSyncConnection =\n            (await _organizationConnectionRepository.GetByOrganizationIdTypeAsync(selfHostedOrganizationDetails.Id,\n                OrganizationConnectionType.CloudBillingSync)).FirstOrDefault();\n        if (billingSyncConnection == null)\n        {\n            throw new NotFoundException(\"Unable to get Cloud Billing Sync connection\");\n        }\n\n        var license =\n            await _getSelfHostedOrganizationLicenseQuery.GetLicenseAsync(selfHostedOrganizationDetails, billingSyncConnection);\n        var currentOrganization = await _organizationRepository.GetByLicenseKeyAsync(license.LicenseKey);\n\n        await _updateOrganizationLicenseCommand.UpdateLicenseAsync(selfHostedOrganizationDetails, license, currentOrganization);\n\n        var config = billingSyncConnection.GetConfig<BillingSyncConfig>();\n        config.LastLicenseSync = DateTime.Now;\n        billingSyncConnection.SetConfig(config);\n        await _organizationConnectionRepository.ReplaceAsync(billingSyncConnection);\n    }\n}\n","sourceCodeStart":103,"sourceCodeEnd":136,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Controllers/SelfHosted/SelfHostedOrganizationLicensesController.cs#L103-L136","documentation":"Thrown as a NotFoundException (HTTP 404) by the cloud-billing-sync license-refresh path when the organization has no OrganizationConnection of type CloudBillingSync. The controller looks up connections of that type for the (validated) self-hosted org details and, finding none, treats the missing connection as a not-found resource rather than a permission error.","triggerScenarios":"Triggering a license sync/refresh for a self-hosted org that has not yet configured a Cloud Billing Sync organization connection, or whose connection was deleted. Caller is already verified as the org owner.","commonSituations":"Org admin sets up license sync but never created the CloudBillingSync connection in the web vault; connection was removed; wrong org selected; migration where the connection did not carry over.","solutions":["Create an OrganizationConnection of type CloudBillingSync for this organization in the web vault before refreshing.","Confirm the connection is active and its BillingSyncConfig is populated (API key, etc.).","Verify you are operating on the correct org id that owns the connection.","Re-establish the connection if it was deleted and retry the refresh."],"exampleFix":"// before: refresh with no CloudBillingSync connection -> 404\n//   await UpdateLicenseSyncAsync(orgId);\n//\n// after: ensure connection exists first\nvar conn = await GetCloudBillingSyncConnection(orgId);\nif (conn == null) {\n  await CreateCloudBillingSyncConnection(orgId, billingSyncApiKey);\n}\nawait UpdateLicenseSyncAsync(orgId);","handlingStrategy":"validation","validationCode":"// Ensure a CloudBillingSync connection exists before refreshing the license\nconst conns = await getOrgConnections(orgId, 'CloudBillingSync');\nif (conns.length === 0) {\n  await createCloudBillingSyncConnection(orgId, billingSyncApiKey);\n}\nawait refreshLicenseSync(orgId);","typeGuard":"function hasCloudBillingSyncConnection(list) {\n  return Array.isArray(list) && list.some(c => c.type === 'CloudBillingSync' && c.enabled);\n}","tryCatchPattern":"try {\n  await refreshLicenseSync(orgId);\n} catch (e) {\n  if (e.status === 404 && /billing sync connection/i.test(e.message)) {\n    await createCloudBillingSyncConnection(orgId, billingSyncApiKey);\n    await refreshLicenseSync(orgId); // one retry after setup\n  } else throw e;\n}","preventionTips":["Create the CloudBillingSync organization connection (with a valid config) before triggering sync.","Confirm the BillingSyncConfig is populated (API key, etc.).","Operate on the org id that actually owns the connection."],"tags":["licensing","self-hosted","billing-sync","organization-connections","http-404"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}