Skip to content

fix(parser): decode signed Kafka header bytes as UTF-8 - #5839

Merged
svozza merged 2 commits into
aws-powertools:mainfrom
vishwakt:fix/5830-parser-kafka-signed-header-bytes
Oct 24, 2026
Merged

svozza merged 2 commits into
aws-powertools:mainfrom
vishwakt:fix/5830-parser-kafka-signed-header-bytes

Conversation

@vishwakt

Copy link
Copy Markdown
Contributor

Summary

KafkaRecordSchema decoded each header value with String.fromCodePoint(...value), which throws a RangeError that escapes safeParse. Lambda sends header bytes as signed Java bytes, so any byte of 128 or above arrives negative, and every real event with a non-ASCII or binary header failed to parse. Spreading the array also exceeded the call stack for large headers. This validates header values as bytes and decodes them without spreading.

Changes

  • Validated header values in packages/parser/src/schemas/kafka.ts with z.array(z.number().int().min(-128).max(255)), accepting Lambda's signed form and unsigned hand-written values, so out-of-range values become Zod issues instead of a thrown RangeError.
  • Decoded header values with Buffer.from(value).toString('utf8'). Buffer.from masks each number to a byte, so negative values convert, and there is no argument-count limit. This matches how @aws-lambda-powertools/kafka decodes headers in packages/kafka/src/consumer.ts. ASCII headers decode exactly as before.
  • Added a record with the signed UTF-8 header from Powertools for Python's MSK test event (powertools-lambda-python#6878) to packages/parser/tests/events/kafka/base.json, and updated the schema and envelope tests to expect it decoded as hello-world-ë. Against the schema on main, the record makes nine existing Kafka tests fail with a RangeError.
  • Added tests for out-of-range header values (-129, 256, 1.5), which return an issue from safeParse, and for a 200,000-byte header, which decodes without exceeding the call stack.

The Python record has "key": null, which our schema rejects, since key is an optional string. I left key out of the added record so the test stays about headers. Whether real events can send a null key is a separate question.

Issue number: closes #5830


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

KafkaRecordSchema decoded each header value with
String.fromCodePoint(...value), which throws a RangeError that escapes
safeParse. Lambda sends header bytes as signed Java bytes, so any byte
>= 128 arrives negative and every real event with a non-ASCII or binary
header failed to parse. Spreading the array also exceeded the call stack
for large headers.

Validate header values as integers from -128 to 255, so out-of-range
values become Zod issues, and decode with Buffer.from(value).toString('utf8'),
which masks each number to a byte, has no argument limit, and matches how
@aws-lambda-powertools/kafka decodes headers.

Add a record with a signed UTF-8 header to the Kafka test event, matching
the one Powertools for Python added, and cover out-of-range values and a
large header.

Closes aws-powertools#5830
@svozza

svozza commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Nice. Merged!

@svozza
svozza merged commit 6e22577 into aws-powertools:main Oct 24, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M PR between 30-99 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Kafka header transform throws RangeError, escaping safeParse

2 participants