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

Python: FunctionCallContent.combine_arguments drops a streamed "{}" chunk, producing invalid JSON arguments

Open Beginner friendly
#14,512 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 4 days

@VANDRANKI is already working on this.

Since Sep 30, 2026.

  • #14513 by @VANDRANKI — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
ai

Research direction

Start in python/semantic_kernel/contents/function_call_content.py at FunctionCallContent.combine_arguments(), then inspect the reduction in chat_completion_client_base.py and the OpenAI connector's tool.function.arguments deltas. Reproduce the listed delta sequences and verify that accumulated arguments preserve each "{}" chunk, produce valid JSON, and no longer raise FunctionCallInvalidArgumentsException.

Written by the indexing model from the issue text.

Description

python triage

What happens

When a streamed function call has its arguments split across chunks, FunctionCallContent.combine_arguments() silently drops any chunk that is exactly the two characters {}. The accumulated arguments string is then invalid JSON, and parse_arguments() raises FunctionCallInvalidArgumentsException.

Where

python/semantic_kernel/contents/function_call_content.py, FunctionCallContent.combine_arguments():

EMPTY_VALUES: Final[list[str | None]] = ["", "{}", None]
...
        if arg1 in EMPTY_VALUES and arg2 in EMPTY_VALUES:
            return "{}"
        if arg1 in EMPTY_VALUES:
            return arg2 or "{}"
        if arg2 in EMPTY_VALUES:
            return arg1 or "{}"
        return (arg1 or "") + (arg2 or "")

The "{}" sentinel is meant for a whole "no arguments" value, for example a first chunk that is just a placeholder. But __add__ is also used to concatenate raw token deltas (chat_completion_client_base.py does reduce(lambda x, y: x + y, all_messages) over the stream, and the OpenAI connector passes tool.function.arguments from each delta straight into FunctionCallContent(arguments=...)). A mid-stream fragment that happens to equal {} is an empty JSON object that belongs in the output, not a placeholder. It gets thrown away.

Repro

Tested with semantic-kernel==1.44.1. I diffed function_call_content.py against current main and the file is identical.

from functools import reduce
from semantic_kernel.contents import StreamingChatMessageContent, FunctionCallContent, AuthorRole

def chunk(i, args):
    fc = FunctionCallContent(id="call_1" if i == 0 else None, index=0,
                             name="search-find" if i == 0 else None, arguments=args)
    return StreamingChatMessageContent(role=AuthorRole.ASSISTANT, items=[fc], choice_index=0)

deltas = ['{"query":"x","filters":', '{}', '}']
full = reduce(lambda a, b: a + b, [chunk(i, d) for i, d in enumerate(deltas)])
call = [i for i in full.items if isinstance(i, FunctionCallContent)][0]
print("concatenated deltas:", "".join(deltas))
print("accumulated        :", call.arguments)
call.parse_arguments()

Output:

concatenated deltas: {"query":"x","filters":{}}
accumulated        : {"query":"x","filters":}
...
semantic_kernel.exceptions.content_exceptions.FunctionCallInvalidArgumentsException: Function Call arguments are not valid JSON even after preprocessing.

Other splits fail the same way:

deltas accumulated expected
'{"a":[', '{}', ',', '{}', ']}' {"a":[,]} {"a":[{},{}]}
'{"a": {"b":', '{}', '}}' {"a": {"b":}} {"a": {"b":{}}}

Expected

The accumulated string equals the concatenation of the deltas, so the arguments parse to {"query": "x", "filters": {}}.

Actual

The {} delta is dropped, the JSON is broken, and the auto function invocation path fails on parse_arguments() for a call the model produced correctly.

Note on likelihood

This needs a tokenizer or provider to emit {} as its own delta. That is a valid and common token for compact JSON, and some providers chunk arbitrarily, but I did not capture it from a live model. The defect is in the merge logic and reproduces deterministically with the deltas above.

Suggested fix

Only treat "{}" as an empty placeholder when the other side is empty or is itself a complete-looking object. One option: keep "" and None as always-empty, and treat "{}" as empty only when it is the accumulated arg1 and arg2 starts a new object, or when both sides are "{}". Otherwise fall through to plain string concatenation.

I searched issues and PRs for combine_arguments, EMPTY_VALUES, FunctionCallContent.__add__ and streaming function-call argument problems. Nothing covers this.

Dominant language
C#
Stars
28.6k
Forks
4.8k
Avg merge
1d 18h
Merged PRs (30d)
19

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

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 microsoft/semantic-kernel

All issues in microsoft/semantic-kernel

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.