Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Event stream decoder reports a checksum mismatch when the checksum is read in parts

Open
#3,371 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

@lazerg is already working on this.

Since Oct 10, 2026.

  • #3373 by @lazerg — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
25/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
php
Domain
api

Research direction

The bug is in NonSeekableStreamDecodingEventStreamIterator, where the trailing four-byte checksum is read with a single read(4) call before comparison. Check how the existing partial-read handling for headers and payload works, then make the checksum read loop until it has four bytes or the stream ends. Done when the reproduction script no longer throws and a partial-read test with one-byte reads passes. Pull request #3373 is already open against this issue, so review it first.

Written by the indexing model from the issue text.

Description

Describe the bug

NonSeekableStreamDecodingEventStreamIterator rejects a valid event when the stream returns its trailing checksum in more than one read.

The decoder handles partial reads for the headers and payload, but reads the four checksum bytes with a single read(4) call. A stream can return fewer bytes even when more data is still coming.

Expected Behavior

I think the decoder should keep reading until it has all four checksum bytes, or reaches the end of the stream.

Current Behavior

The example below throws:

Aws\Api\Parser\Exception\ParserException: Message checksum mismatch.

The frame has a valid checksum. It parses successfully when the read limit is removed.

Reproduction Steps

This example doesn’t need an AWS account or make any network requests.

Install aws/aws-sdk-php version 3.399.2, then run:

<?php

require 'vendor/autoload.php';

use Aws\Api\Parser\NonSeekableStreamDecodingEventStreamIterator;
use GuzzleHttp\Psr7\FnStream;
use GuzzleHttp\Psr7\NoSeekStream;
use GuzzleHttp\Psr7\Utils;

$headers = '';

foreach ([
    ':message-type' => 'event',
    ':event-type' => 'messageStop',
    ':content-type' => 'application/json',
] as $name => $value) {
    $headers .= chr(strlen($name)).$name.chr(7)
        .pack('n', strlen($value)).$value;
}

$payload = '{"stopReason":"end_turn"}';
$prelude = pack('NN', 16 + strlen($headers) + strlen($payload), strlen($headers));
$frame = $prelude.hash('crc32b', $prelude, true).$headers.$payload;
$frame .= hash('crc32b', $frame, true);

$body = Utils::streamFor($frame);
$stream = new NoSeekStream(FnStream::decorate($body, [
    'read' => static fn ($length) => $body->read(min(1, $length)),
]));

$iterator = new NonSeekableStreamDecodingEventStreamIterator($stream);
$iterator->rewind();

Possible Solution

Read the complete trailing checksum before comparing it. The existing partial-read test could also include reads limited to one byte.

Additional Information/Context

This appears to be a missed case from #3165, which fixed partial reads for #3110. Its test limits reads to 20 bytes, so the four-byte checksum still arrives in one read.

I also reproduced this with a local HTTP server that sends the checksum in two parts. The same single checksum read is still present on master.

SDK version used

3.399.2

Environment details

PHP 8.4.25, Ubuntu 24.04.

Generated by Codex, and reviewed by @binaryfire.

Dominant language
PHP
Stars
6.2k
Forks
1.3k
Avg merge
2d 7h
Merged PRs (30d)
11

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from aws/aws-sdk-php

All issues in aws/aws-sdk-php

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.