Event key tuple collapses when a key field is missing a required value

Author: danotorreyCreated Sep 17, 2026Updated Sep 17, 2026

This came out of a Claude code review of https://github.com/Graylog2/graylog2-server/pull/27365 (see https://github.com/Graylog2/graylog2-server/pull/27365#discussion_r4039789770) and hasn't been verified against a running instance yet, so treat the description below as an unconfirmed reading of the code. It appears to be a pre-existing problem, independent of that PR, so filing it separately.

When an event definition uses templated custom fields as its event key, and those fields have Require all values to be set enabled, a field whose template variable has no value resolves to an error value. TemplateFieldValueProvider.isValidTemplate returns false and the provider returns FieldValue.error() (graylog2-server/src/main/java/org/graylog/events/fields/providers/TemplateFieldValueProvider.java). EventProcessorEngine.emitEvents then filters error (and null) values out of the key tuple before calling setKeyTuple (graylog2-server/src/main/java/org/graylog/events/processor/EventProcessorEngine.java).

Because the missing entry is dropped rather than represented as an empty slot, the remaining values shift position and two semantically different events can end up with an identical key.

With key_spec: ["src_host", "dst_host"], both templated with Require all values to be set:

Message src_host dst_host Key tuple Key
only source_host present web01 (no value, error) ["web01"] web01
only dest_host present (no value, error) web01 ["web01"] web01

The engine does notice the mismatch and logs Key spec <...> for event <...> cannot be fulfilled, and the code carries a TODO: What should we do in this case? Set no key at all? Set an incomplete key?, so the behavior looks unresolved rather than intentional. Anything that keys off key_tuple (event keys shown in the UI and API, and any consumer that treats the key as an identity for the event) may therefore conflate distinct events.

Worth deciding what the correct behavior is: keep a placeholder for the missing position so the tuple stays positional, drop the key entirely when the spec can't be fulfilled, or something else. Whatever we land on should also be applied to the new absent-value handling being added in https://github.com/Graylog2/graylog2-server/pull/27365, which skips setting the field altogether and would take the same path.

Notes

Nobody has reproduced this on a running instance yet. It's a Claude observation from reading the code path during review of https://github.com/Graylog2/graylog2-server/pull/27365, so the first step here is confirming the behavior with an event definition keyed on two templated fields that have Require all values to be set enabled.

Source: Graylog2/graylog2-server