Move the IoT Edge runtime and daemon to the 1.6 LTS line - #441
Conversation
Gate result: this does not work. Do not merge.I was wrong about #435's blocker, and the gate proved it. Controlled A/BSame repo content, three lines apart, on the same gate pipeline:
On 1.6: 7/7 The mechanical part of the change is fine
What actually failsC / C# / Node — the four Python is considerably worse — 16 failures per job, and not confined to So it is not one wrapper, one language, or one module identity. Clients broadly cannot establish connections to edgeHub 1.6 in this deployment. Where my #439/#440 reasoning was right, and where it was wrongRight: the wrapper no longer dies. Previously the follow-on failures were Wrong: I treated the crash as the whole story. It was not. With the crash fixed, a real connection failure against edgeHub 1.6 is still there — previously hidden behind the louder process death. #435's blocker is genuine. ConsequenceStaying on 1.5 is correct. 1.5 is a supported LTS (1.5.44), so there is no end-of-life exposure — that was resolved by #436 when it moved off 1.4. This PR is the next step, not an urgent one, and it should not merge until edgeHub 1.6 works here. Marking as draft. Investigation continues; the python job is the better reproducer, since it fails more broadly and includes a leaf device. |
Correction and root cause directionMy previous comment implied the failure was TLS 1.3 specific. An interleaved re-run shows that was an artefact of test ordering. The finding is broader. edgeHub 1.6's MQTT head on port 8883 mostly never completes a TLS handshake at all. Interleaved controlRaw TLS + MQTT
Same probe, same pipeline, same VM image, same deployment manifest. The only difference is Failure shapeedgeHub's DotNetty buffer-pool debug lines appear at the exact millisecond the client connects, so the connection is accepted and reaches the MQTT head: Why it looked language-specific
ScopeOnly the DotNetty MQTT head is affected. edgeHub's Kestrel HTTPS on 443 is unaffected —
Gate stays on 1.5. See the next comment for the root cause. |
There was a problem hiding this comment.
Pull request overview
Moves the repo’s default IoT Edge “release line” setting from 1.5 to 1.6 so the default edgeAgent/edgeHub image tags and the host aziot-edge/aziot-identity-service package line stay aligned via IOTHUB_E2E_EDGE_RELEASE_LINE.
Changes:
- Update
EDGE_RELEASE_LINEdefault from1.5→1.6for edgeAgent/edgeHub image tags. - Update
install-iotedge.shdefault package line from1.5→1.6. - Update test-runner documentation to reflect the new default release line.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| bin/deploy/edge_configuration.py | Changes the default IoT Edge release line used for module image tags. |
| scripts/new/install-iotedge.sh | Changes the default IoT Edge release line used to select/pin host daemon packages. |
| test-runner/README.md | Updates documentation for the default IOTHUB_E2E_EDGE_RELEASE_LINE value. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Root cause: edgeHub 1.6 ships a 2018 build of DotNetty's TLS handlerThe 1.6 images resolve Read from the running containers (
DotNetty's own
So 1.6 runs a TLS handler that predates the fix explicitly made for net8, on net10. How the downgrade happenedA transitive-resolution regression, not an intentional pin. Both versions are
Present in 1.6.0-rc.1, 1.6.0 and 1.6.1; absent in 1.5.43 and 1.5.44. That matches the observed history: the first 1.6 trial ran 1.6.0, before 1.6.1 existed, so the 1.6.1 base-image refresh is not involved. EffectRaw TLS + MQTT CONNECT probe against the deployed edgeHub, client max TLS version alternating 1.2/1.3 per attempt (a CONNACK of any return code counts as answered):
Reproduced across three runs. Failure shape: TCP is accepted and reaches DotNetty — its buffer-pool debug lines appear at the exact millisecond — then nothing. No ServerHello, no CONNACK, and no log line naming the client even at Only the DotNetty MQTT head is affected. edgeHub's Kestrel HTTPS on 443 is unaffected —
Why it looks language-specific
Secondary observationOn 1.6 arms the agent reached 98% memory (18 warnings in one run, 10 in another); the 1.5 arms running the identical probe produced zero. Consistent with stalled handshakes retaining buffers. Not required for the failure — the full gate run where all six FixFor the product, in Confirming that 0.7.6 is sufficient on net10 requires building the edgeHub image, which needs the product repo's toolchain and has not been done. DotNetty 0.8.0 (2026-01-08) carries further TLS work — "Deferred processing of pending data packets to ensure upstream handlers receive TlsHandshakeCompletionEvent before application data" — and later commits mention TLS 1.3 connection drops when application data is sent before authentication completes. Consistent with that: a probe that waited 250 ms after the handshake before sending CONNECT occasionally succeeded on 1.6 where an immediate send did not. For this repoNo workaround exists on our side — the defect is inside the published image and cannot be configured around. The gate stays on 1.5 (1.5.44, supported LTS, 6/6 |
Mechanism confirmed: each stalled handshake leaks memory in edgeHub 1.6Host and per-container memory measured immediately before and after the same 20-attempt probe, on both lines:
On 1.6 the other containers were squeezed out as edgeHub grew — This ties the whole failure together:
DotNetty 0.7.5 (2022-08-31) is "Fix infinite loop caused by TlsHandler" — an unbroken loop in the handler matches both symptoms exactly: no bytes are ever written back, and buffers accumulate without bound. 0.6.0 predates that fix, and 1.6 ships 0.6.0. Memory pressure is a consequence, not the trigger: the earlier full gate run where all six The fix is unchanged — pin |
IOTHUB_E2E_EDGE_RELEASE_LINE has defaulted to 1.5 since #436. 1.6 is the current LTS (1.6.0 daemon, 1.6.1 module images) and is serviced through 2028-11-14; 1.5 is the previous LTS. Move the single knob to 1.6, which moves both the edgeAgent/edgeHub image tags and the pinned host aziot-edge/aziot-identity-service packages together. aziot-edge 1.6.0-1 and aziot-identity-service 1.6.0-1 are both present in the Microsoft feed for ubuntu/22.04 (jammy) and ubuntu/24.04 (noble), which are the only Linux agent images these pipelines use, so the pin in install-iotedge.sh resolves. This retries the 1.6 move that #435 abandoned. Every one of the 16 failures recorded there (build 161703) was the same thing in a different language: friendMod's node wrapper on localhost:8098 stopped answering, producing "too many 500 error responses" on connect2 and then ConnectionRefused for the rest of the suite. That was the missing 'error' listener in the node wrapper, since fixed by #439 and #440 -- the same UnauthorizedError ("mqtt.js returned Failure on first connection (Not authorized)") that killed the wrapper on 1.6 was also observed on 1.5 in build 161989, so it was never a 1.6 regression. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5344b14 to
dfd4d50
Compare
Unblocked: green on edgeHub 1.6.2edgeHub 1.6.2 shipped 2026-08-26 and contains the fix for the MQTT/TLS failure described above — its changelog lists "Fix Edge Hub MQTT/TLS failures", and Re-ran the full gate on this branch, rebased on current master:
Same three-line change as before; only the runtime it deploys against has changed. Taking this out of draft. One thing to know when reading this: the |
What
Move the IoT Edge release line from
1.5to1.6. Three defaults:bin/deploy/edge_configuration.pyEDGE_RELEASE_LINE—azureiotedge-agent/-hubimage tagsscripts/new/install-iotedge.shaziot_edge_line— hostaziot-edge/aziot-identity-servicepackagestest-runner/README.mdIOTHUB_E2E_EDGE_RELEASE_LINEoverrides all three together, so images and daemon cannot drift.Why now
1.6 is the current LTS, serviced through 2028-11-14. 1.5 is the previous LTS.
This PR was blocked until now: edgeHub 1.6.0/1.6.1 could not complete a TLS handshake on the MQTT head, so every
edgehub_modulejob failed. That was an IoT Edge defect — the 1.6 images resolvedDotNetty.Handlers/Codecs/Codecs.Mqttdown to 0.6.0 (October 2018) instead of 0.7.6, because the .NET 10 + device SDK update removed the transitive reference that had been raising them. The details are in the comments below.Fixed in edgeHub 1.6.2 (2026-08-26), which pins those packages back to 0.7.6. The
:1.6tag now resolves to it.Gate result
Full gate on this branch, rebased on current master, is green: 20/20 jobs, including 6/6
edgehub_module— the jobs that were 0/6 on 1.6.1.Daemon and images match, both on the 1.6 line:
The daemon stays at 1.6.0 — 1.6.2 updated only the module images.
Blast radius
Changes edgeAgent/edgeHub and the host daemon for every language gate — Java, Python, Node, C, C#. Nothing else pins the version: no pipeline definition and no consuming repo's
horton-e2e.yamlsetsIOTHUB_E2E_EDGE_RELEASE_LINEor the image overrides. A gate needing to stay on 1.5 can setIOTHUB_E2E_EDGE_RELEASE_LINE=1.5in its own pipeline without reverting this.Validation
Local, before the gate:
bash -n scripts/new/install-iotedge.shclean;python -m py_compile bin/deploy/edge_configuration.pyclean.edge_configuration.pyand asserted behaviour: defaultEDGE_RELEASE_LINEis1.6;_verify_image_on_release_lineacceptsazureiotedge-hub:1.6and:1.6.2and rejects:1.5.latest_version_on_lineawk exercised against realapt-cache madisonoutput:1.6→1.6.0-1,1.5→1.5.21-1, a line with no packages → hard error rather than a silent fall through to latest.aziot-edge=1.6.0-1andaziot-identity-service=1.6.0-1are published forubuntu-22.04(jammy) andubuntu-24.04(noble), the only Linux agent images these pipelines use.Then the full gate, as above.