Skip to content

Fix AwaitMessageTrigger crash on tombstone messages when apply_function is unset - #69665

Merged
potiuk merged 1 commit into
apache:mainfrom
TimurRakhmatullin86:fix/kafka-trigger-tombstone-null-value
Aug 1, 2026
Merged

Fix AwaitMessageTrigger crash on tombstone messages when apply_function is unset#69665
potiuk merged 1 commit into
apache:mainfrom
TimurRakhmatullin86:fix/kafka-trigger-tombstone-null-value

Conversation

@TimurRakhmatullin86

Copy link
Copy Markdown
Contributor

When AwaitMessageTrigger is used without an apply_function (supported since #55437), the trigger calls message.value().decode("utf-8") on every polled message. For a tombstone message — value() is None, a routine occurrence on log-compacted topics where a null value is the deletion marker — this raises AttributeError: 'NoneType' object has no attribute 'decode', crashing the trigger and failing the deferred task.

This PR treats a tombstone the same way as any other non-matching message: no event is emitted, the offset is committed (when commit_offset=True, matching the existing non-matching path so the tombstone is not re-read forever after a restart), and the trigger keeps polling.

Why skip rather than emit: the trigger's contract is already truthiness-based (if event:), so a None payload cannot be yielded on this path today, and a TriggerEvent(None) would carry no usable payload downstream. Users who need to react to tombstones can already do so via apply_function, which receives the raw message (including value() is None) and can map it to any truthy payload. Surfacing tombstones from the no-apply_function convenience path would be a separate opt-in feature; crashing on them is a bug.

Tests:

  • test_trigger_run_tombstone_message_keeps_polling — regression test: poll() returns a null-value message; asserts the trigger neither raises nor yields and commits the tombstone offset. Fails on main with the exact AttributeError above.
  • test_trigger_run_without_apply_function_yields_message_value — asserts the happy path still yields the decoded payload.
  • MockedMessage now has a value() method: the apply_function=None case of test_trigger_run_good previously passed for the wrong reason — the mock lacked value(), so the task finished via this same AttributeError, satisfying task.done() is True.

No behavior change for non-null messages or when apply_function is set. Empty (b"") payloads were already treated as non-events by the if event: check — unchanged.

@potiuk potiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 11, 2026

@potiuk potiuk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fix for a genuinely routine case — a null value on a log-compacted topic is the deletion marker, not an anomaly, so crashing the trigger on it is a real problem rather than an edge case.

The part I like is that it routes tombstones into the existing non-matching branch rather than special-casing them. That branch already commits the offset when commit_offset is enabled, which matters more than it might look: without it a tombstone sitting at the head of a compacted topic would be re-read on every restart and the trigger would never progress past it. Worth having pinned in the test, which you did:

assert commit_mock.mock_calls == [call(message=message, asynchronous=False)]

alongside assert task.done() is False. The latter is what fails on main, where the AttributeError completes the task.

One thing worth being aware of rather than changing here: a non-null but empty payload (b"") decodes to "" and is also skipped, since the contract is truthiness-based. That is pre-existing behaviour and this PR does not alter it, but it means "no event emitted" covers slightly more than just tombstones.

Rebased onto main before merging, as the branch had drifted well behind.


Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting

…on is unset

Signed-off-by: Timur Rakhmatullin <174210871+TimurRakhmatullin86@users.noreply.github.com>
@potiuk
potiuk force-pushed the fix/kafka-trigger-tombstone-null-value branch from 3c24a76 to 891bc5a Compare August 1, 2026 03:11
@potiuk
potiuk merged commit 6669e7e into apache:main Aug 1, 2026
98 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants