Skip to content

Skip sub events for non-dict job returns in the event tagger (#69730)#69731

Open
ggiesen wants to merge 1 commit into
saltstack:3006.xfrom
ggiesen:fix-69730-event-list-return
Open

Skip sub events for non-dict job returns in the event tagger (#69730)#69731
ggiesen wants to merge 1 commit into
saltstack:3006.xfrom
ggiesen:fix-69730-event-list-return

Conversation

@ggiesen

@ggiesen ggiesen commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Stops the master's event tagger from crashing on non-dict job returns. A failing state compilation returns a list of error strings (or a plain string from some renderers) rather than a mapping of per-state results, and _fire_ret_load_specific_fun assumed a dict:

File "salt/utils/event.py", line 941, in _fire_ret_load_specific_fun
    for tag, data in ret.items():
AttributeError: 'list' object has no attribute 'items'

The broad except turned this into Event iteration failed with exception: ... logged at ERROR for every failed compile. The integration tests that assert that message never appears (tests/pytests/integration/states/test_state_test.py) fail whenever they share a run with a failing compile - this is the second failure cluster behind the "Rocky Linux 9 integration tcp/zeromq" noise on 3006.x PRs (12 occurrences in run 28764048341 job 85297152499; the first cluster, leaked minion keys, is addressed by #69729 and absent from that run).

A non-dict return has no state tags to fire sub events for, so it is now skipped at debug level after the return shape is resolved (the guard also covers the multi-function branches, where ret.get(fun, {}) can produce a non-dict).

What issues does this PR fix or reference?

Fixes #69730
Refs #69728

Previous Behavior

Every failing state compilation made the master log Event iteration failed with exception: 'list' object has no attribute 'items', and the test_state_test integration tests failed on the logged message.

New Behavior

Non-dict returns are skipped quietly; dict-shaped returns fire the per-tag failure events exactly as before.

Merge requirements satisfied?

  • Tests written/updated
  • Changelog

Two regression tests drive the production entry point fire_ret_load with a SUB_EVENT function and non-zero retcode: the list-return test reproduces the exact failed-compile load shape and fails on the previous code via the logged error; the dict-return test pins the two sub events (the old-style <state>.<func> duplicate tag and the namespaced salt/job/<jid>/sub/<id>/error/<fun> tag) with their enriched payload, guarding against overcorrection.

Commits signed with GPG?

No

A failing state compilation returns a list of error strings (or a
plain string from some renderers) rather than a mapping of per-state
results. _fire_ret_load_specific_fun assumed a dict and crashed on
ret.items(), logging 'Event iteration failed with exception: list
object has no attribute items' at ERROR for every failed compile. The
integration tests that assert that message never appears
(tests/pytests/integration/states/test_state_test.py) fail whenever
they share a run with a failing compile, which is part of the Rocky
Linux 9 integration job noise on 3006.x.

There are no state tags in a non-dict return, so skip it at debug
level instead. Dict-shaped returns keep firing the per-tag failure
events unchanged, covered by a new regression pair: the list-return
test fails on the previous code via the logged error, and the
dict-return test pins the two sub events (old-style dup tag and the
namespaced job error tag) with their enriched payload.

Fixes saltstack#69730
Refs saltstack#69728
@ggiesen ggiesen requested a review from a team as a code owner July 6, 2026 05:34
@dwoz dwoz added the test:full Run the full test suite label Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants