website/docs/updates/breaking-changes/v0-86-0-data-channel-protocol-upgrade.md
:::note This guide is accurate as of Flet 0.86.0. Later releases might add new APIs or additional migration paths.
The breaking changes and deprecations index lists the guides created for each release. :::
Flet 0.86.0 introduces dedicated data channels for widgets that need to move bulk binary data (image frames, audio buffers, ML tensors) between Dart and Python without going through the MsgPack control protocol.
Enabling this required a one-time upgrade of the Flet protocol's wire format:
flet run dev mode over UDS / TCP) now use
4-byte little-endian length-prefixed framing. The previous streaming
msgpack.Unpacker.feed decode is gone.dart_bridge FFI, Pyodide
postMessage) now puts a 1-byte type discriminator at the head of each
packet:
0x00 — MsgPack-encoded Flet control frame (widget state, events) — same
contents as before, just with a type byte in front.0x01 — raw DataChannel frame ([channel_id:u32 LE][payload]).The new format is not backwards-compatible: a Flet 0.85 client cannot talk
to a Flet 0.86 server, and vice versa. The flet-cli dev server and the
in-process Python runtime were upgraded together in this release.
Flet's previous wire format on UDS / TCP relied on msgpack.Unpacker.feed to
re-assemble messages from arbitrary byte-stream chunks. That works for
MsgPack-only traffic but doesn't compose with a second logical stream of raw
bytes — you can't tell a partial MsgPack value from the start of a raw frame
without an out-of-band marker.
Adding the 1-byte type byte + 4-byte length prefix solves this in the smallest possible way:
[length][type][...], fan out by type byte, no streaming
decoder state to maintain.postMessage, dart_bridge) drop
the length prefix since each message is already one packet; they keep the
type byte.If you only use flet build artifacts or run flet run with the matching
flet package version (the default install pulls both at once), there's
nothing to do. The CLI and the runtime are version-locked.
flet-cli and the flet Python package from different installsMake sure both come from the same release. The common gotcha is a global
flet install plus a project-local flet in .venv at different versions
— upgrade or pin both to ≥ 0.86.0 (or both to ≤ 0.85.x).
A version mismatch will surface as a connection failure during flet run
with a parse error in the dev-server log.
The wire format changed. Update your encoder/decoder:
postMessage): each
message's first byte is the type discriminator, the rest is the payload.Treat 0x01 (raw DataChannel) frames as opaque if you don't use data channels
— forward them along or drop them, never feed them to your MsgPack decoder.
StreamingMsgpackDeserializerThe Dart-side class package:flet/src/transport/streaming_msgpack_deserializer.dart
is removed. There are no public consumers — it was an internal helper for
stream-transport framing that's no longer needed now that every packet is
length-delimited. If you imported it (you shouldn't have), decode each inbound
buffer with one-shot msgpack.deserialize(bytes) instead.
MatplotlibChartCanvasMatplotlibChartCanvas now transports its apply_full / apply_diff /
clear frames through a [DataChannel] rather than _invoke_method arguments.
The Python-facing method signatures are unchanged (apply_full(image_bytes: bytes), etc.), and they remain the documented API. But if you subclassed the
canvas and overrode the Dart-side _invokeMethod handler, that override no
longer fires — the Dart side now consumes a 1-byte opcode + PNG payload from
the channel directly.
0.86.0flet.DataChannel (Python) and FletBackend.openDataChannel (Dart) — see the module docstrings in flet/data_channel.py; dedicated reference pages will be added in a follow-up.