Description:
When using `mysql.connector.aio` to establish a connection to a MySQL 5.6 server (including version 5.6.51), a `TypeError: cannot unpack non-iterable NoneType object` occurs if the `ssl_disabled` parameter is *not explicitly provided* in the connection arguments. This issue is specific to MySQL 5.6; connections to MySQL 5.7 and later versions do not exhibit this behavior, even under similar conditions. **Although MySQL 5.6 has reached its End-of-Life, there is still a significant installed base, making this compatibility issue relevant for many users.**
This issue is specific to `mysql.connector.aio`; the synchronous `mysql.connector` does not exhibit this behavior and connects successfully under similar conditions (e.g., when connecting to a server requiring secure transport with a trusted certificate, it defaults to using SSL and connects).
The `TypeError` originates from `mysql.connector.aio/connection.py` at the line `cipher, tls_version, _ = self._socket._writer.get_extra_info("cipher")`. It appears that `self._socket._writer.get_extra_info("cipher")` returns `None` when `ssl_disabled` is implicitly determined (i.e., not explicitly passed), and the code attempts to unpack this `None` value, leading to the `TypeError`. This suggests a compatibility issue in `mysql.connector.aio`'s SSL/TLS handshake process specifically with MySQL 5.6.
This behavior forces users to explicitly specify `ssl_disabled` (either `True` or `False`) in their connection configurations when connecting to MySQL 5.6, which is an unnecessary and cumbersome requirement. The desired behavior is for the connector to implicitly handle SSL negotiation based on server capabilities and provided certificates (as `mysql.connector` does).
How to repeat:
1. Set up a MySQL 5.6 server (e.g., version 5.6.51). This server can be configured with `--require_secure_transport=ON` or not. The `TypeError` occurs regardless of the server's `require_secure_transport` setting, as long as `ssl_disabled` is not explicitly provided in the client.
2. Attempt to connect to this MySQL 5.6 server using `mysql.connector.aio.connect()` without explicitly providing the `ssl_disabled` parameter in the connection arguments.
```python
import asyncio
import mysql.connector.aio
async def connect_and_fail():
config = {
"host": "your_mysql_5_6_host",
"port": 3306, # or your specific port
"user": "your_user",
"password": "your_password",
"database": "your_database"
# ssl_disabled parameter is NOT explicitly provided
}
try:
conn = await mysql.connector.aio.connect(**config)
print("Connected successfully (unexpected for this bug report)")
await conn.close()
except Exception as e:
print(f"Connection failed: {e}")
if __name__ == "__main__":
asyncio.run(connect_and_fail())
```
### Expected Behavior:
`mysql.connector.aio.connect()` should not raise a `TypeError` when `ssl_disabled` is not explicitly provided, especially when connecting to MySQL 5.6. Instead, it should:
* Attempt to negotiate SSL by default if no SSL parameters are provided, and connect successfully if the server supports it (e.g., with a trusted certificate).
* If the server requires SSL but no valid SSL configuration is provided by the client, it should raise a clear `DatabaseError` (e.g., `3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.`) or a relevant SSL error, similar to `mysql.connector`.
### Actual Behavior:
A `TypeError: cannot unpack non-iterable NoneType object` is raised during the connection attempt when `ssl_disabled` is not explicitly provided, specifically when connecting to MySQL 5.6.
### Workaround:
Explicitly passing `ssl_disabled=True` or `ssl_disabled=False` (depending on the desired SSL behavior) to `mysql.connector.aio.connect()` resolves the `TypeError`. However, this is an undesirable workaround as it forces explicit configuration where implicit behavior is expected and handled correctly by `mysql.connector`.
### Environment:
* MySQL Server Version: 5.6 (e.g., 5.6.51)
* Python Version: 3.8 - 3.14
* `mysql-connector-python` Version: 9.0 - 9.5
* Operating System: Linux, macOS, Windows
Suggested fix:
The synchronous `mysql.connector` library correctly handles SSL negotiation by default, even when `ssl_disabled` is not explicitly provided, and does not exhibit this `TypeError`. It successfully connects to servers with trusted certificates or raises appropriate `DatabaseError` (e.g., `3159`) if secure transport is required but not met.
It is suggested that `mysql.connector.aio` align its default SSL negotiation behavior with that of `mysql.connector`. Specifically, when `ssl_disabled` is not explicitly provided in the connection arguments, `mysql.connector.aio` should:
- Attempt to negotiate an SSL connection by default.
- Avoid raising a `TypeError` due to `get_extra_info("cipher")` returning `None` in such scenarios.
- If an SSL connection cannot be established (e.g., due to server requirements or certificate issues), it should raise a more informative `DatabaseError` or SSL-specific error, consistent with `mysql.connector`.
Description: When using `mysql.connector.aio` to establish a connection to a MySQL 5.6 server (including version 5.6.51), a `TypeError: cannot unpack non-iterable NoneType object` occurs if the `ssl_disabled` parameter is *not explicitly provided* in the connection arguments. This issue is specific to MySQL 5.6; connections to MySQL 5.7 and later versions do not exhibit this behavior, even under similar conditions. **Although MySQL 5.6 has reached its End-of-Life, there is still a significant installed base, making this compatibility issue relevant for many users.** This issue is specific to `mysql.connector.aio`; the synchronous `mysql.connector` does not exhibit this behavior and connects successfully under similar conditions (e.g., when connecting to a server requiring secure transport with a trusted certificate, it defaults to using SSL and connects). The `TypeError` originates from `mysql.connector.aio/connection.py` at the line `cipher, tls_version, _ = self._socket._writer.get_extra_info("cipher")`. It appears that `self._socket._writer.get_extra_info("cipher")` returns `None` when `ssl_disabled` is implicitly determined (i.e., not explicitly passed), and the code attempts to unpack this `None` value, leading to the `TypeError`. This suggests a compatibility issue in `mysql.connector.aio`'s SSL/TLS handshake process specifically with MySQL 5.6. This behavior forces users to explicitly specify `ssl_disabled` (either `True` or `False`) in their connection configurations when connecting to MySQL 5.6, which is an unnecessary and cumbersome requirement. The desired behavior is for the connector to implicitly handle SSL negotiation based on server capabilities and provided certificates (as `mysql.connector` does). How to repeat: 1. Set up a MySQL 5.6 server (e.g., version 5.6.51). This server can be configured with `--require_secure_transport=ON` or not. The `TypeError` occurs regardless of the server's `require_secure_transport` setting, as long as `ssl_disabled` is not explicitly provided in the client. 2. Attempt to connect to this MySQL 5.6 server using `mysql.connector.aio.connect()` without explicitly providing the `ssl_disabled` parameter in the connection arguments. ```python import asyncio import mysql.connector.aio async def connect_and_fail(): config = { "host": "your_mysql_5_6_host", "port": 3306, # or your specific port "user": "your_user", "password": "your_password", "database": "your_database" # ssl_disabled parameter is NOT explicitly provided } try: conn = await mysql.connector.aio.connect(**config) print("Connected successfully (unexpected for this bug report)") await conn.close() except Exception as e: print(f"Connection failed: {e}") if __name__ == "__main__": asyncio.run(connect_and_fail()) ``` ### Expected Behavior: `mysql.connector.aio.connect()` should not raise a `TypeError` when `ssl_disabled` is not explicitly provided, especially when connecting to MySQL 5.6. Instead, it should: * Attempt to negotiate SSL by default if no SSL parameters are provided, and connect successfully if the server supports it (e.g., with a trusted certificate). * If the server requires SSL but no valid SSL configuration is provided by the client, it should raise a clear `DatabaseError` (e.g., `3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.`) or a relevant SSL error, similar to `mysql.connector`. ### Actual Behavior: A `TypeError: cannot unpack non-iterable NoneType object` is raised during the connection attempt when `ssl_disabled` is not explicitly provided, specifically when connecting to MySQL 5.6. ### Workaround: Explicitly passing `ssl_disabled=True` or `ssl_disabled=False` (depending on the desired SSL behavior) to `mysql.connector.aio.connect()` resolves the `TypeError`. However, this is an undesirable workaround as it forces explicit configuration where implicit behavior is expected and handled correctly by `mysql.connector`. ### Environment: * MySQL Server Version: 5.6 (e.g., 5.6.51) * Python Version: 3.8 - 3.14 * `mysql-connector-python` Version: 9.0 - 9.5 * Operating System: Linux, macOS, Windows Suggested fix: The synchronous `mysql.connector` library correctly handles SSL negotiation by default, even when `ssl_disabled` is not explicitly provided, and does not exhibit this `TypeError`. It successfully connects to servers with trusted certificates or raises appropriate `DatabaseError` (e.g., `3159`) if secure transport is required but not met. It is suggested that `mysql.connector.aio` align its default SSL negotiation behavior with that of `mysql.connector`. Specifically, when `ssl_disabled` is not explicitly provided in the connection arguments, `mysql.connector.aio` should: - Attempt to negotiate an SSL connection by default. - Avoid raising a `TypeError` due to `get_extra_info("cipher")` returning `None` in such scenarios. - If an SSL connection cannot be established (e.g., due to server requirements or certificate issues), it should raise a more informative `DatabaseError` or SSL-specific error, consistent with `mysql.connector`.