Skip to content

Fix #2061 — Remote configuration silently disabled on self-provisioning gateways#2139

Open
apachler wants to merge 1 commit into
thingsboard:masterfrom
apachler:bugfix/remote-config
Open

Fix #2061 — Remote configuration silently disabled on self-provisioning gateways#2139
apachler wants to merge 1 commit into
thingsboard:masterfrom
apachler:bugfix/remote-config

Conversation

@apachler

@apachler apachler commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Problem

When a gateway authenticates via the provisioning section (self-onboarding), remote configuration is silently non-functional: enabling remote logging, changing settings, or adding a connector from the ThingsBoard
gateway dashboard has no effect and nothing is persisted to disk. The only visible hint is an unrelated Unexpected message from topic 'v1/devices/me/attributes' debug line (benign SDK noise — the payload is delivered).

Root cause

A provisioning gateway has no security section in its configuration — credentials are obtained at runtime and stored separately in provisioned_credentials.json, and TBClient never writes them back into the config.

RemoteConfigurator.init calls _get_general_config_in_local_format(), which assumed a security section always exists:

security_section = adopted_general_config.get('security') # -> None for a provisioning gateway
security_type = security_section.get('type', 'accessToken') # -> AttributeError: 'NoneType' object has no attribute 'get'

That AttributeError is caught and swallowed by TBGatewayService.__init_remote_configuration, leaving __remote_configurator = None. As a result:

  • the config-request consumer thread (_process_config_request) never starts,
  • the gateway never sends its current configuration to ThingsBoard,
  • every remote update is queued to RECEIVED_UPDATE_QUEUE but never consumed → silently dropped.

A secondary issue affects the same gateways: __is_security_match(None, …) returns False, so once initialized, every general_configuration push forces a full reconnect via _apply_connection_config (consistent with the
reconnect churn reported in #2124).

Fix

thingsboard_gateway/tb_utility/tb_gateway_remote_configurator.py:

  1. _get_general_config_in_local_format — only normalize the security section when it is present, so the method no longer raises for provisioning gateways.
  2. __is_security_match — when neither side has a security section, return True (no spurious "connection changed" → no needless reconnect); when only one side has it, return False without dereferencing None.

No public API or config-format changes; behavior is unchanged for gateways that use an explicit security section.

How to reproduce (before this PR)

  1. Configure a gateway with a provisioning section and remoteConfiguration: true, and no security section.
  2. Start it; observe Failed to initialize remote configuration and that the gateway never reports its config to TB.
  3. Add a connector from the gateway dashboard → it is never written to disk / never loaded.

Testing

  • RemoteConfigurator constructs successfully with a provisioning config; the consumer thread starts (previously raised AttributeError).
  • Driving the full pipeline, a remote-added Modbus connector now persists both its connector file and tb_gateway.json.
  • __is_security_match truth table verified: (None, {})→True, ({}, {})→True, (None, token)→False, (tokenA, tokenA)→True, (tokenA, tokenB)→False.
  • Verified against the real thingsboard/tb-gateway:3.8.2 image: stock image raises AttributeError; with the guard it returns cleanly with no spurious security key.

Compatibility

Backward compatible. Gateways using accessToken / usernamePassword / tlsAccessToken are unaffected; only the previously-crashing no-security (provisioning) path changes.

Closes #2061.

…sboard#2061)

A gateway that authenticates via the `provisioning` section has no
`security` section in its configuration (credentials are obtained at
runtime and stored in provisioned_credentials.json; TBClient never writes
them back into the config). RemoteConfigurator init calls
_get_general_config_in_local_format(), which dereferenced the missing
security section (security_section.get('type')) and raised AttributeError.
__init_remote_configuration swallows that exception, so __remote_configurator
stayed None: the config-request consumer thread never started, the gateway
never sent its configuration to ThingsBoard, and every remote update
(connector adds, remote logging, etc.) was silently dropped.

- Guard the security-section normalization so it is skipped when no
  security section is present.
- Treat two empty/absent security sections as a match in
  __is_security_match, so provisioning gateways no longer force a needless
  reconnect on every general_configuration push, and never dereference None
  when only one side has a section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Remote config not working

1 participant