Use ObjectEmpty() instead of array-only Empty() on a JSON object - #4548
Open
Daksha1611 wants to merge 1 commit into
Open
Use ObjectEmpty() instead of array-only Empty() on a JSON object#4548Daksha1611 wants to merge 1 commit into
Daksha1611 wants to merge 1 commit into
Conversation
computeDeltaImpl() builds its result with delta.SetObject(), so nestedDelta
is always an object. Testing it with Value::Empty() is an array-only
accessor:
// rapidjson/document.h:1649
bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
// rapidjson/document.h:1197
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
RAPIDJSON_ASSERT is assert() and is not overridden anywhere in the tree, so a
build with assertions live (-c dbg, see Makefile:118) aborts with
"Assertion `IsArray()' failed" as soon as a streamed delta contains a nested
object present in both snapshots - ordinary streaming of a tool call whose
arguments contain a nested JSON object.
Under NDEBUG the assert disappears and data_.a.size aliases data_.o.size
(both unions open with SizeType size), so the wrong accessor returns the
right number. That is why this has gone unnoticed; release behaviour is
unchanged by this commit.
The four tool parsers that compute the same kind of delta already use
ObjectEmpty() - hermes3, llama3, mistral and phi4 - so this brings the
builder in line with them. The other two Value::Empty() call sites in the
tree are genuinely arrays and are left alone: openai_api_handler.cpp:736
operates on a GetArray() result, and openai_responses.cpp:522 is guarded by
an IsArray() check immediately above.
Tests: the five delta assertions in partial_json_builder_test.cpp made the
same misuse, so the suite itself aborted under -c dbg before reaching the
production call. Adds computeDeltaWithUnchangedNestedMember, which pins the
branch whose emptiness result actually decides the output - an unchanged
nested object must contribute no member to the delta.
Daksha1611
marked this pull request as ready for review
September 12, 2026 07:09
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.
🛠 Summary
Fixes #4547.
computeDeltaImpl()builds its result withdelta.SetObject(), sonestedDeltais always an object, but it was tested withValue::Empty(). In the pinned RapidJSON that accessor is array-only:RAPIDJSON_ASSERTisassert()and is not overridden anywhere in the tree, so a build with assertions live (-c dbg,Makefile:118) aborts withAssertion `IsArray()' failedas soon as a streamed delta contains a nested object present in both snapshots — ordinary streaming of a tool call with nested arguments. UnderNDEBUGthe assert disappears anddata_.a.sizealiasesdata_.o.size, so the wrong accessor returns the right number. Release behaviour is unchanged by this PR.The four tool parsers computing the same kind of delta already use
ObjectEmpty()(hermes3, llama3, mistral, phi4), so this brings the builder in line. The other twoValue::Empty()call sites insrc/are genuinely arrays and are left alone.The five delta assertions in
partial_json_builder_test.cppmade the same misuse, so the suite aborted under-c dbgbefore reaching the production call; they now useObjectEmpty(). AddscomputeDeltaWithUnchangedNestedMemberfor the branch whose emptiness result decides the output. Note that test passes both before and after in a release build, for the aliasing reason above — its value is running correctly under assertions.I have no OVMS build container available, so this is not compiled against the full tree and CI will need to confirm the build. I did reproduce the abort and the fix against the exact pinned RapidJSON revision from
WORKSPACE:102. Draft for that reason.🧪 Checklist