RocketChat/Rocket.Chat · warning · Error

error-unregistering-provider

Error message

error-unregistering-provider

What it means

Generic wrapper thrown by OutboundCommunicationBridge.unRegisterProvider when getOutboundService().outboundMessageProvider.unregisterProvider throws. The original error is logged with msg 'Failed to unregister provider' before this opaque message is thrown. Signals that cleanup of a previously registered phone/email outbound provider failed.

Source

Thrown at apps/meteor/app/apps/server/bridges/outboundCommunication.ts:42

	}

	protected async registerEmailProvider(provider: IOutboundEmailMessageProvider, appId: string): Promise<void> {
		try {
			this.orch.debugLog(`App ${appId} is registering an email outbound provider.`);
			getOutboundService().outboundMessageProvider.registerEmailProvider(provider);
		} catch (err) {
			this.orch.getRocketChatLogger().error({ appId, err, msg: 'Failed to register email provider' });
			throw new Error('error-registering-provider');
		}
	}

	protected async unRegisterProvider(provider: IOutboundMessageProviders, appId: string): Promise<void> {
		try {
			this.orch.debugLog(`App ${appId} is unregistering an outbound provider.`);
			getOutboundService().outboundMessageProvider.unregisterProvider(appId, provider.type);
		} catch (err) {
			this.orch.getRocketChatLogger().error({ appId, err, msg: 'Failed to unregister provider' });
			throw new Error('error-unregistering-provider');
		}
	}
}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Read the server log for the original `err` to see the concrete failure.
  2. Track registration state in your App and only unregister what you successfully registered.
  3. Make onDisable resilient: wrap unregister in try/catch and log, since failing to unregister should not break disable.
  4. Ensure the type passed to unregister matches the type used at registration.

Example fix

// before
await outbound.unRegisterProvider(provider, appId); // throws if never registered

// after
if (this.registered) {
  try {
    await outbound.unRegisterProvider(provider, appId);
  } catch (e) {
    console.warn(' unregister failed', e.message);
  }
  this.registered = false;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// only unregister what you successfully registered
if (!this.registeredTypes.has(provider.type)) {
  this.app.getLogger().debug(`Skipping unregister for ${provider.type}: not registered`);
  return;
}
await outbound.unRegisterProvider(provider, appId);

Try / catch

try {
  await outbound.unRegisterProvider(provider, appId);
  this.registeredTypes.delete(provider.type);
} catch (e) {
  // failing to unregister must not break disable
  this.app.getLogger().warn({ msg: 'Unregister failed', providerType: provider.type, err: e });
}

Prevention

When it happens

Trigger: An App's disable/uninstall hook tries to unregister a provider that was never registered (e.g. registration failed earlier but disable still runs), the provider type does not match any registered one, or the outbound service is already torn down.

Common situations: Asymmetric register/unregister after a failed registration; calling unregister with the wrong type string; uninstall of an App whose onEnable never completed; server shutdown race where the outbound service is gone.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/0ec4bf4f938fd6da. Report an issue: GitHub.