Skip to content

Issue 644#645

Merged
shamblett merged 1 commit into
masterfrom
issue644
Apr 18, 2026
Merged

Issue 644#645
shamblett merged 1 commit into
masterfrom
issue644

Conversation

@shamblett

Copy link
Copy Markdown
Owner

Based on my analysis of the codebase and the error provided in the GitHub issue, I have identified exactly under what conditions this LateInitializationError is triggered.

The Trigger Condition
This error occurs when the initial connection attempt fails, and then an auto-reconnect is subsequently triggered (either manually via doAutoReconnect() or automatically if configured to
try again).

This explains why the issue isn't seen in the examples or unit tests: those tests invariably ensure the initial connection succeeds before testing the disconnect/reconnect logic.

Why it Happens

  1. Missing Initialization on Failure: When a user calls client.connect(), the underlying connection class (e.g., MqttServerNormalConnection) attempts to establish a socket. If this succeeds, it initializes the messageStream and readWrapper variables before listening to the stream. However, if the initial socket connection fails (e.g., broker is down, network timeout), the catchError block is triggered, and these fields are never initialized.
  2. Re-using the Connection Object: When a reconnection is triggered (like when the user calls doAutoReconnect(...)), the connection handler purposely reuses the existing connection object because autoReconnectInProgress is true. It then calls the connectAuto() method instead of connect().
  3. The Oversight in connectAuto: In all connection classes (e.g., MqttServerNormalConnection, MqttServerSecureConnection, MqttBrowserWsConnection, etc.), the connectAuto() method successfully establishes the new socket and starts listening (_startListening()), but it completely omits the initialization of messageStream and readWrapper.
  4. The Crash: Because the initial connect() failed to initialize them, and connectAuto() didn't initialize them either, they remain uninitialized. As soon as the newly connected broker sends its first byte of data, onData is fired, attempts to call messageStream.addAll(data), and throws the LateInitializationError.

How to Fix It
To fix this bug, we need to ensure messageStream and readWrapper are initialized in the .then() blocks of the connectAuto() methods across all connection implementation classes, just as
they are in the regular connect() methods.

Based on my analysis of the codebase and the error provided in the GitHub issue, I have identified exactly under what conditions this LateInitializationError is triggered.

  The Trigger Condition
  This error occurs when the initial connection attempt fails, and then an auto-reconnect is subsequently triggered (either manually via doAutoReconnect() or automatically if configured to
  try again).

  This explains why the issue isn't seen in the examples or unit tests: those tests invariably ensure the initial connection succeeds before testing the disconnect/reconnect logic.

  Why it Happens
   1. Missing Initialization on Failure: When a user calls client.connect(), the underlying connection class (e.g., MqttServerNormalConnection) attempts to establish a socket. If this
      succeeds, it initializes the messageStream and readWrapper variables before listening to the stream. However, if the initial socket connection fails (e.g., broker is down, network
      timeout), the catchError block is triggered, and these fields are never initialized.
   2. Re-using the Connection Object: When a reconnection is triggered (like when the user calls doAutoReconnect(...)), the connection handler purposely reuses the existing connection
      object because autoReconnectInProgress is true. It then calls the connectAuto() method instead of connect().
   3. The Oversight in connectAuto: In all connection classes (e.g., MqttServerNormalConnection, MqttServerSecureConnection, MqttBrowserWsConnection, etc.), the connectAuto() method
      successfully establishes the new socket and starts listening (_startListening()), but it completely omits the initialization of messageStream and readWrapper.
   4. The Crash: Because the initial connect() failed to initialize them, and connectAuto() didn't initialize them either, they remain uninitialized. As soon as the newly connected broker
      sends its first byte of data, onData is fired, attempts to call messageStream.addAll(data), and throws the LateInitializationError.

  How to Fix It
  To fix this bug, we need to ensure messageStream and readWrapper are initialized in the .then() blocks of the connectAuto() methods across all connection implementation classes, just as
  they are in the regular connect() methods.
@shamblett shamblett merged commit 19fb357 into master Apr 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant