Skip to content

fix: accept empty-data final exec_chunk to complete the waiter - #109

Merged
blaspat merged 1 commit into
mainfrom
fix/exec-chunk-empty-final
Aug 13, 2026
Merged

fix: accept empty-data final exec_chunk to complete the waiter#109
blaspat merged 1 commit into
mainfrom
fix/exec-chunk-empty-final

Conversation

@blaspat

@blaspat blaspat commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the server-side half of the exec disconnect on workmac.

The node streams exec_chunk messages; the final chunk (more=false) carries empty data by design — its payload is the exit_code / status / duration_ms / truncated metadata, not output bytes. But _handle_exec_chunk rejected empty data before reading the more flag, so every exec's completion metadata was dropped.

Result (confirmed from audit.log + server logs):

  • exec_chunk ... missing or invalid data warning on every exec
  • the waiter never completes cleanly → the connection tears down right after each exec (close 1006 (abnormal closure): unexpected EOF)

Change

wsserver/server.py — read more first, then only require non-empty data for intermediate chunks (more=true). An empty-data final chunk now decodes to b"" and completes the waiter with its metadata.

more = raw.get("more", True)
data_b64 = raw.get("data")
if not isinstance(data_b64, str) or (not data_b64 and more):
    ...  # reject

Test plan

  • 3 new regression tests in tests/test_exec_chunk.py:
    • empty-data final chunk after an intermediate chunk → waiter completes with metadata + assembled output
    • empty-data final chunk as the only chunk (zero-output command) → waiter completes, empty temp file
    • empty-data intermediate chunk is still rejected → no chunk state created, waiter stays pending
  • pytest -q → 49 passed
  • ruff check → clean

Related

  • Go side already merged: blaspat/hermes-node#121 (demuxer tail more=true) and #122 (NoResponse ordering). This PR completes the pair — without it the final chunk's metadata is dropped.

The final chunk (more=false) carries empty data by design — its payload
is the exit_code/status/duration_ms/truncated metadata, not output
bytes. _handle_exec_chunk rejected empty data before reading `more`,
so the completion metadata was dropped and the waiter stranded until
the per-call timeout (surfacing as "exec_chunk ... missing or invalid
data" in the server log, then a node disconnect on exec).

Only intermediate chunks (more=true) now require non-empty data;
base64.b64decode("") yields b"" so an empty-data final chunk decodes
cleanly and appends nothing.

Signed-off-by: Blasius Patrick <blasius.patrick@gmail.com>
@blaspat
blaspat merged commit fa8b3c9 into main Aug 13, 2026
2 checks passed
@blaspat
blaspat deleted the fix/exec-chunk-empty-final branch August 13, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant