## Summary
Every HTTPS/TLS connection attempt made through the HTTP(S) client (`AT+QHTTPGETEX` with the SSL context bound via `AT+QHTTPCFG=“sslctxid”`) or directly through the raw SSL socket API (`AT+QSSLOPEN`) fails during the TLS handshake. `AT+QIGETERROR` confirms this precisely: **`579, ssl handshake failed`**.
This reproduces regardless of:
- **Target server** — reproduced against our own infrastructure and against `httpbin.org` (a standard public HTTPS host with no unusual TLS requirements: no client-cert request, no renegotiation, standard cipher suites).
- **`seclevel`** — tested `0` (no validation at all), `1` (server auth only), and `2` (mutual TLS); all fail identically.
- **Certificate/key content** — the exact same cert material (CA, client cert, client key) is used successfully elsewhere on the same session (see below), ruling out bad/expired/mismatched certs.
- **AT command family** — reproduced both via `AT+QHTTPGETEX` (which reports the less specific `+QHTTPGET: 701`, HTTP(S) “unknown error”) and via `AT+QSSLOPEN` directly, bypassing the HTTP(S) client entirely.
Meanwhile, on the **same modem, same session**:
- `AT+QMTOPEN` (MQTT mutual TLS, port 8883, separate SSL context, separate AT command family) connects successfully every time.
- `AT+QHTTPGETEX` over **plain HTTP** (no TLS) to the same external hosts succeeds completely (200 response, correct body content read back via `AT+QHTTPREADFILE`/`AT+QFREAD`).
This points at something specific to how the TLS handshake is performed when driven via `AT+QSSLOPEN` / `AT+QHTTPCFG=“sslctxid”`, distinct from whatever `AT+QMTOPEN` does internally, since the latter clearly works with equivalent SSL context settings.
## Reproduction
### 1. SSL context configuration (context ID 1)
```
AT+QSSLCFG=“sslversion”,1,4
AT+QSSLCFG=“ciphersuite”,1,0XFFFF
AT+QSSLCFG=“seclevel”,1,2 // also tested with 0 and 1, no change in outcome
AT+QSSLCFG=“ignorelocaltime”,1,1
AT+QSSLCFG=“sni”,1,1
AT+QSSLCFG=“cacert”,1,“ota_ca.pem”
AT+QSSLCFG=“clientcert”,1,“ota_client.pem”
AT+QSSLCFG=“clientkey”,1,“ota_key.pem”
AT+QSSLCFG=“renegotiation”,1,1 // also tested with 0, no change in outcome
```
All of the above return `OK`.
### 2a. Reproduction via the HTTP(S) client
```
AT+QHTTPCFG=“contextid”,1
AT+QHTTPCFG=“sslctxid”,1
AT+QHTTPCFG=“contenttype”,2
AT+QHTTPCFG=“custom_header”,“Authorization:Token ”
AT+QHTTPURL=,300
AT+QHTTPCFG=“requestheader”,0
AT+QHTTPGETEX=300,0,262144
```
Result (URC, ~350–600 ms later): `+QHTTPGET: 701`
Follow-up `AT+QIGETERROR` at this point returns `0, operate successfully` — not useful for this failure path.
### 2b. Reproduction via the raw SSL socket API (bypasses the HTTP(S) client entirely)
Using the same SSL context 1 configured above:
```
AT+QSSLOPEN=1,1,0,“httpbin.org”,443
```
Result (URC, ~1.1 s later): `+QSSLOPEN: 0,579`
Follow-up `AT+QIGETERROR`:
```
+QIGETERROR: 579,ssl handshake failed
```
### What works, same session, same modem
- `AT+QMTOPEN` — MQTT mutual TLS to our broker (port 8883) — succeeds, every time.
- `AT+QHTTPGETEX` over plain HTTP (no TLS) to `httpbin.org` — succeeds, `+QHTTPGET: 0,200,402`, full response body correctly read back.
## What we’ve ruled out on our side
- **Certificate/key validity** — the same CA/client-cert/client-key material that fails here is used successfully for `AT+QMTOPEN`'s mutual TLS in the same session.
- **CA trust / seclevel** — reproduced even with `seclevel=0` (all validation disabled).
- **Server-specific TLS config or CDN quirks** — reproduced against `httpbin.org`, a plain, standard public HTTPS host, not just our own server.
- **HTTP command sequencing/parameters** — reproduced via `AT+QSSLOPEN` directly, with no `AT+QHTTPxxx` commands involved at all.
- **`renegotiation`** — tested both `1` and `0` against `httpbin.org` via `AT+QSSLOPEN`; both fail identically (`+QSSLOPEN: 0,579`, `AT+QIGETERROR: 579,ssl handshake failed`). Forcing renegotiation on was not the cause.
## Documentation checked locally (no answer found)
We checked the following against this exact failure and found nothing conclusive:
- `Quectel_EG800Q&EG91xQ_Series_SSL_Application_Note_V1.3` — Table 4 (Result Codes) only documents `` 550–574; `579` is not listed, and the table has no entry for a TLS handshake/certificate-validation-specific failure at all despite this being the SSL-specific document.
- `Quectel_EG800Q&EG91xQ_Series_TCP(IP)_Application_Note_V1.2` — same table, same range (550–574), same gap.
- `Quectel_EG800Q&EG91xQ_Series_AT_Commands_Manual_V1.1` — lists `AT+QSSLOPEN` but no extended error table.
- `Quectel_EG800Q&EG91xQ_Series_HTTP(S)_Application_Note_V1.3` — documents `701`–`730`; `701` is literally “HTTP(S) unknown error” (the generic catch-all), and every failure we’ve reproduced lands on this generic code rather than any of the more specific ones in that range (e.g. `709` network deactivated, `714` DNS error, `716` socket connect error) — suggesting the failure isn’t a routine network condition the module already knows how to classify.
## Questions for Quectel
1. Is `=579` (“ssl handshake failed” per `AT+QIGETERROR`) documented anywhere with a more specific sub-reason, or is there a debug/verbose logging mode we can enable on the module to capture the actual TLS alert or failure stage?
2. Is this a known issue on firmware `EG916QGLLGR01A05M04_A0.301.A0.301` specifically affecting `AT+QSSLOPEN` / `AT+QHTTPCFG=“sslctxid”`-driven handshakes, while `AT+QMTOPEN`'s internal TLS handling is unaffected?
3. Is there a newer firmware revision that addresses SSL/TLS handshake reliability for the HTTP(S) client or raw SSL socket API?
4. Are there any additional required `AT+QSSLCFG`/`AT+QHTTPCFG` parameters, or a required command ordering, not covered in SSL Application Note V1.3 / HTTP(S) Application Note V1.3, that could explain a handshake failure specific to these two command families?
## Environment
- Module firmware: `EG916QGLLGR01A05M04_A0.301.A0.301`
- Host MCU: Espressif ESP32-S3
- Reproducible on demand; happy to provide full AT command traces (UART logs) on request.