fix(messages): reject blank message bodies at every write layer - #5505
Open
Dinehub1 wants to merge 1 commit into
Open
fix(messages): reject blank message bodies at every write layer#5505Dinehub1 wants to merge 1 commit into
Dinehub1 wants to merge 1 commit into
Conversation
An empty message signed, published, and was accepted like any other message: `check_content` enforced only a ceiling, never a floor. The caller got `accepted: true` and exit code 0 for a message that said nothing, and readers got a row with an author and a timestamp and no body -- indistinguishable from a delivery failure. The path that produced it in practice: agent shells run every command with stdin on /dev/null (buzz-dev-mcp shell.rs), so a `--content -` that lost its upstream pipe read "" rather than erroring. Guard all three layers: - buzz-sdk: `check_content_not_blank` in build_message (kind:9), build_forum_post (45001), build_forum_comment (45003), and build_edit (40003), mirroring the guard build_git_patch already had. Catches every caller, not just the CLI. - buzz-cli: reject in cmd_send_message with an error that names the cause, so the stdin case says so and the caller gets exit 1 and can retry instead of silently "succeeding". - buzz-relay: reject blank kinds 9/40002/40003/45001/45003 at ingest, the one chokepoint every client shares. Caption-less attachments stay legal throughout: a body whose payload is an imeta-tagged image is not blank. That exemption is load-bearing for edits, where dropping a caption but keeping the image arrives as empty content plus an imeta overlay. Signed-off-by: Brand Collabs <brandcollabs1@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
An empty message signs, publishes, and is accepted like any other message.
check_contentenforces only a ceiling, never a floor, so""passes every layer:buzz-sdk:build_message/build_forum_post/build_forum_comment/build_editonly bound the max sizebuzz-cli:cmd_send_messagecallsvalidate_content_size, which has an explicit test asserting""is validbuzz-relay: ingest has no empty-content rejection for message kindsThe caller gets
accepted: trueand exit code 0 for a message that says nothing. Readers get a row with an author and a timestamp and no body — indistinguishable from a delivery failure.How it happens in practice
Agent shells run every command with stdin on
/dev/null(buzz-dev-mcp/src/shell.rs:175). The base prompt recommendsprintf '…' | buzz messages send … --content -for multiline bodies. Drop the pipe and--content -reads from a closed stdin, yields"", and silently publishes a blank message while reporting success — so the agent believes it spoke and moves on.Observed repeatedly with a managed agent: the model produced output (539, 381, then 1290, 616 output tokens across two turns), the turn ended without error, and the published message was empty.
Fix
Guard all three layers, mirroring the
content.trim().is_empty()checkbuild_git_patchalready had:check_content_not_blankinbuild_message(kind:9),build_forum_post(45001),build_forum_comment(45003), andbuild_edit(40003). Catches every caller, not just the CLI.cmd_send_messagevia the pure, testableblank_content_messagehelper. The error names the actual cause, and the stdin case says so explicitly, so callers get exit 1 and can retry instead of silently "succeeding".Caption-less attachments stay legal throughout: a body whose payload is an imeta-tagged image is not blank. That exemption is load-bearing for edits specifically — dropping a caption while keeping the image arrives as empty content plus an imeta overlay.
validate_content_sizeis deliberately left accepting"". It is a size-only helper shared with paths where empty content is legitimate; the floor belongs at the message layer.Testing
15 new tests: empty, whitespace-only (
" ","\n","\t\n \r\n"), media-exempt, per-kind coverage, and for the CLI that the stdin message names stdin while the argv message does not.cargo fmt --all --checkandcargo clippy --all-targetsclean. Full pre-push gate green.Verified end to end against the rebuilt binary, through the multicall shim the agent actually uses:
--content -with stdin on/dev/null--content ""--content " "printf 'hello\n' | … --content -One pre-existing unrelated failure,
api::mesh_demo::demo_join_forwarded_arm_round_trips_echo, reproduces identically on a cleanmain.🤖 Generated with Claude Code