Skip to content

fix: normalize msgpack Binary scalars for deterministic cache hashing#7075

Open
majiayu000 wants to merge 3 commits intoflyteorg:masterfrom
majiayu000:fix/issue-6776-deterministic-msgpack-cache-hash
Open

fix: normalize msgpack Binary scalars for deterministic cache hashing#7075
majiayu000 wants to merge 3 commits intoflyteorg:masterfrom
majiayu000:fix/issue-6776-deterministic-msgpack-cache-hash

Conversation

@majiayu000
Copy link
Copy Markdown

Tracking issue

Closes #6776

Why are the changes needed?

DictTransformer uses msgpack for serialization, which does not enforce key ordering. When the same dict is serialized on different machines or Python versions, the key order can vary, producing different bytes and therefore different cache hashes. This causes unexpected cache misses for identical inputs.

What changes were proposed in this pull request?

In hashify() (hashing.go), added a normalization step for Binary scalars with the msgpack tag: unmarshal the msgpack bytes, then re-marshal to JSON (which sorts map keys alphabetically at every nesting level). The normalized JSON bytes replace the original value for hashing purposes only — stored data is unchanged.

If normalization fails (e.g., non-standard msgpack), the original bytes are used as-is, preserving backward compatibility.

Changes:

  • Added normalizeMsgpackBytes() helper in hashing.go
  • Called it from hashify() for Binary literals tagged msgpack
  • Added tests covering flat dicts, nested dicts, non-msgpack tags, and invalid input fallback

How was this patch tested?

Added the following tests in hashing_test.go:

  • TestHashLiteralMap_MsgpackBinaryDeterministic: verifies that two msgpack-encoded maps with identical content but different key orders produce the same hash, including nested structures
  • TestHashify_NonMsgpackBinaryTag: verifies Binary literals with non-msgpack tags are not modified
  • TestNormalizeMsgpackBytes_InvalidInput: verifies graceful fallback on invalid msgpack input

All existing tests pass:

cd flyteplugins && go test ./go/tasks/pluginmachinery/catalog/ -v

Labels

  • fixed: Bug fix for non-deterministic cache hashing

Check all the applicable boxes

  • I updated the documentation accordingly.
  • All new and existing tests passed.
  • All commits are signed-off.

DictTransformer serializes dicts via msgpack which does not enforce key
ordering. Identical dicts with different key orderings produce different
byte sequences, leading to unexpected cache misses.

Add normalizeMsgpackBytes() in hashify() that unmarshals msgpack bytes
and re-marshals to JSON (which sorts map keys deterministically) before
hashing. This handles nested dicts and lists. If normalization fails,
the original bytes are used unchanged.

Closes flyteorg#6776

Signed-off-by: majiayu000 <1835304752@qq.com>
- Rename shadowed variable v → elem in toJSONCompatible range loop
- Allocate new slice in []interface{} case instead of mutating in-place
- Add test for normalizeMsgpackBytes with invalid/corrupted input
- Add test for non-msgpack binary tag passthrough

Signed-off-by: majiayu000 <1835304752@qq.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 22, 2026

Codecov Report

❌ Patch coverage is 80.55556% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.96%. Comparing base (f3ab1b7) to head (4e89316).

Files with missing lines Patch % Lines
...lugins/go/tasks/pluginmachinery/catalog/hashing.go 80.55% 6 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #7075      +/-   ##
==========================================
+ Coverage   56.95%   56.96%   +0.01%     
==========================================
  Files         931      931              
  Lines       58188    58224      +36     
==========================================
+ Hits        33141    33170      +29     
- Misses      22005    22011       +6     
- Partials     3042     3043       +1     
Flag Coverage Δ
unittests-datacatalog 53.51% <ø> (ø)
unittests-flyteadmin 53.14% <ø> (ø)
unittests-flytecopilot 43.06% <ø> (ø)
unittests-flytectl 64.02% <ø> (ø)
unittests-flyteidl 75.71% <ø> (ø)
unittests-flyteplugins 60.22% <80.55%> (+0.06%) ⬆️
unittests-flytepropeller 53.65% <ø> (ø)
unittests-flytestdlib 63.02% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: majiayu000 <1835304752@qq.com>
@majiayu000 majiayu000 marked this pull request as ready for review March 22, 2026 21:54
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.

[BUG] DictTransformer has non-deterministic serialization causing unexpected cache misses

1 participant