# json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 1024 (char 1023) when parsing streaming function call arguments

- **ID:** `llm/function-call-arguments-truncated-in-streaming`
- **Domain:** llm
- **Category:** protocol_error
- **Verification:** ai_generated
- **Fix Rate:** 85%

## Root Cause

When streaming function calls, the API sends the arguments in chunks. If the argument string is long, a chunk boundary can split a JSON token (e.g., a string value or key), causing the accumulated arguments to be invalid JSON when parsed incrementally.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| openai==1.30.0 | active | — | — |
| anthropic==0.25.0 | active | — | — |
| mistralai==0.1.0 | active | — | — |

## Workarounds

1. **Accumulate all chunks for a function call before attempting to parse. Wait for the 'finish_reason' to be 'stop' or 'function_call' before parsing the complete arguments string. Example:

full_args = ""
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.function_call and delta.function_call.arguments:
        full_args += delta.function_call.arguments
    if chunk.choices[0].finish_reason:
        break
import json
parsed_args = json.loads(full_args)** (95% success)
   ```
   Accumulate all chunks for a function call before attempting to parse. Wait for the 'finish_reason' to be 'stop' or 'function_call' before parsing the complete arguments string. Example:

full_args = ""
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.function_call and delta.function_call.arguments:
        full_args += delta.function_call.arguments
    if chunk.choices[0].finish_reason:
        break
import json
parsed_args = json.loads(full_args)
   ```
2. **Use the 'incremental parsing' approach with a JSON repair library like 'json-repair' or 'json5' that can handle partial JSON. Example:

import json5
partial_args = ""
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.function_call and delta.function_call.arguments:
        partial_args += delta.function_call.arguments
        try:
            parsed = json5.loads(partial_args)
            # use parsed incrementally
        except Exception:
            pass** (82% success)
   ```
   Use the 'incremental parsing' approach with a JSON repair library like 'json-repair' or 'json5' that can handle partial JSON. Example:

import json5
partial_args = ""
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.function_call and delta.function_call.arguments:
        partial_args += delta.function_call.arguments
        try:
            parsed = json5.loads(partial_args)
            # use parsed incrementally
        except Exception:
            pass
   ```
3. **Set the API parameter 'stream_options' to {'include_usage': True} and use the 'usage' field to detect the end of function call arguments, then parse the complete string.** (75% success)
   ```
   Set the API parameter 'stream_options' to {'include_usage': True} and use the 'usage' field to detect the end of function call arguments, then parse the complete string.
   ```

## Dead Ends

- **Using json.loads() on each individual chunk instead of accumulating** — Individual chunks are not valid JSON; they are partial fragments. json.loads() will always fail on incomplete chunks. (95% fail)
- **Increasing max_tokens to reduce chunking** — max_tokens controls the output length, not the chunk size. The API still sends chunks of arbitrary size regardless of max_tokens. (80% fail)
- **Setting stream_options={'include_usage': True}** — This option controls whether usage information is included in the stream, it has no effect on how function call arguments are chunked or parsed. (90% fail)
