openclaw - ✅(Solved) Fix [Bug]: Gateway serialization produces invalid JSON on tool calls with array fields (intermittent) [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#70537Fetched 2026-04-24 05:56:46
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2labeled ×2commented ×1referenced ×1

The gateway intermittently produces malformed JSON when serializing tool calls that contain array-typed parameters (e.g. fields: [{...}, {...}]). The resulting JSON fails to parse with errors like Expected ',' or ']' after array element in JSON at position NNNN, causing the tool call to fail before reaching the model or being executed.

The bug appears non-deterministic: identical or very similar tool calls sometimes succeed and sometimes fail. Retrying the same operation after a short delay often works, which suggests a serialization race condition or an edge case in how array elements are joined.

Error Message

  1. Observe the error in the Telegram reply or gateway logs: Tool calls containing array parameters should serialize to valid JSON deterministically. Identical inputs should always produce identical, parseable outputs, and the tool call should be dispatched to the downstream tool (filesystem, API, etc.) without a JSON parse error. The gateway returns a JSON parse error to the agent, which surfaces as a visible error message in the chat channel (Telegram). The tool call is aborted. No retry logic kicks in automatically; the user or agent has to manually reattempt the operation or switch to a workaround (e.g. writing via exec with a heredoc instead of a structured editing tool). Error messages observed (sample):

Root Cause

The gateway intermittently produces malformed JSON when serializing tool calls that contain array-typed parameters (e.g. fields: [{...}, {...}]). The resulting JSON fails to parse with errors like Expected ',' or ']' after array element in JSON at position NNNN, causing the tool call to fail before reaching the model or being executed.

The bug appears non-deterministic: identical or very similar tool calls sometimes succeed and sometimes fail. Retrying the same operation after a short delay often works, which suggests a serialization race condition or an edge case in how array elements are joined.

Fix Action

Fix / Workaround

Tool calls containing array parameters should serialize to valid JSON deterministically. Identical inputs should always produce identical, parseable outputs, and the tool call should be dispatched to the downstream tool (filesystem, API, etc.) without a JSON parse error.

The gateway returns a JSON parse error to the agent, which surfaces as a visible error message in the chat channel (Telegram). The tool call is aborted. No retry logic kicks in automatically; the user or agent has to manually reattempt the operation or switch to a workaround (e.g. writing via exec with a heredoc instead of a structured editing tool).

PR fix notes

PR #28: fix(gateway): prevent double-encoding of function call arguments in SSE streaming

Description (problem / solution / changelog)

Summary

In handleOpenResponsesHttpRequest, when streaming tool_calls events, the functionCall.arguments field is already a JSON string. However, it was passed directly to createFunctionCallOutputItem, and then the resulting event object was JSON-stringified again in writeSseEvent(). This caused the already-serialized JSON string inside the arguments field to be double-escaped, producing invalid JSON for arrays/strings containing quotes or newlines.

Root cause confirmed by rafiki270: Array fields containing special characters (quotes/newlines) were not being properly escaped during tool-call argument serialization.

Fix

Parse functionCall.arguments back to a JS object before passing to createFunctionCallOutputItem, so that the single JSON.stringify(event) call in writeSseEvent produces correctly escaped output.

Changed in src/gateway/openresponses-http.ts:

  • Added parsedArguments IIFE that tries JSON.parse(functionCall.arguments) with {} fallback
  • Pass JSON.stringify(parsedArguments) instead of functionCall.arguments to both createFunctionCallOutputItem calls

Testing

Added regression test handles streamed function_call with array args containing special characters in src/gateway/openresponses-http.test.ts that:

  • Mocks agentCommand with pendingToolCalls containing array with quote and newline chars
  • Verifies the SSE response.output_item.added event's arguments field is valid JSON (not double-encoded)
  • Validates the parsed arguments match the original values

Fixes #70537.

Changed files

  • .agents/maintainers.md (removed, +0/-1)
  • .agents/skills/blacksmith-testbox/SKILL.md (added, +340/-0)
  • .agents/skills/openclaw-parallels-smoke/SKILL.md (modified, +16/-0)
  • .agents/skills/openclaw-qa-testing/SKILL.md (modified, +10/-10)
  • .agents/skills/openclaw-release-maintainer/SKILL.md (modified, +237/-55)
  • .agents/skills/openclaw-secret-scanning-maintainer/SKILL.md (modified, +31/-12)
  • .agents/skills/openclaw-secret-scanning-maintainer/scripts/secret-scanning.mjs (modified, +274/-15)
  • .agents/skills/openclaw-test-performance/SKILL.md (added, +134/-0)
  • .agents/skills/openclaw-test-performance/agents/openai.yaml (added, +6/-0)
  • .agents/skills/optimizetests/SKILL.md (added, +41/-0)
  • .agents/skills/optimizetests/agents/openai.yaml (added, +6/-0)
  • .agents/skills/tag-duplicate-prs-issues/SKILL.md (added, +485/-0)
  • .agents/skills/tag-duplicate-prs-issues/agents/openai.yaml (added, +4/-0)
  • .env.example (modified, +2/-0)
  • .github/actionlint.yaml (modified, +2/-0)
  • .github/actions/setup-node-env/action.yml (modified, +7/-7)
  • .github/actions/setup-pnpm-store-cache/action.yml (modified, +4/-17)
  • .github/codex/prompts/docs-agent.md (added, +31/-0)
  • .github/instructions/copilot.instructions.md (modified, +3/-3)
  • .github/labeler.yml (modified, +8/-0)
  • .github/workflows/auto-response.yml (modified, +4/-4)
  • .github/workflows/ci-check-testbox.yml (added, +100/-0)
  • .github/workflows/ci.yml (modified, +1300/-522)
  • .github/workflows/codeql.yml (modified, +9/-8)
  • .github/workflows/control-ui-locale-refresh.yml (modified, +3/-3)
  • .github/workflows/docker-release.yml (modified, +23/-15)
  • .github/workflows/docs-agent.yml (added, +186/-0)
  • .github/workflows/docs-sync-publish.yml (modified, +3/-3)
  • .github/workflows/docs-translate-trigger-release.yml (modified, +2/-1)
  • .github/workflows/install-smoke.yml (modified, +57/-35)
  • .github/workflows/labeler.yml (modified, +16/-16)
  • .github/workflows/macos-release.yml (modified, +3/-3)
  • .github/workflows/openclaw-cross-os-release-checks-reusable.yml (added, +472/-0)
  • .github/workflows/openclaw-live-and-e2e-checks-reusable.yml (added, +902/-0)
  • .github/workflows/openclaw-npm-release.yml (modified, +34/-20)
  • .github/workflows/openclaw-release-checks.yml (modified, +353/-43)
  • .github/workflows/openclaw-scheduled-live-checks.yml (added, +77/-0)
  • .github/workflows/parity-gate.yml (modified, +27/-5)
  • .github/workflows/plugin-clawhub-release.yml (modified, +0/-3)
  • .github/workflows/plugin-npm-release.yml (modified, +0/-3)
  • .github/workflows/qa-live-telegram-convex.yml (added, +342/-0)
  • .github/workflows/sandbox-common-smoke.yml (modified, +4/-1)
  • .github/workflows/stale.yml (modified, +5/-5)
  • .github/workflows/workflow-sanity.yml (modified, +7/-5)
  • .gitignore (modified, +6/-0)
  • .markdownlint-cli2.jsonc (modified, +5/-0)
  • .oxlintrc.json (modified, +96/-3)
  • .pi/prompts/landpr.md (removed, +0/-73)
  • .pi/prompts/reviewpr.md (removed, +0/-134)
  • .pre-commit-config.yaml (modified, +2/-2)
  • .vscode/settings.json (modified, +2/-1)
  • AGENTS.md (modified, +202/-318)
  • CHANGELOG.md (modified, +527/-2)
  • CONTRIBUTING.md (modified, +6/-3)
  • Dockerfile (modified, +7/-1)
  • Dockerfile.sandbox (modified, +1/-1)
  • Dockerfile.sandbox-browser (modified, +1/-1)
  • README.md (modified, +252/-384)
  • SECURITY.md (modified, +5/-0)
  • appcast.xml (modified, +228/-187)
  • apps/android/app/build.gradle.kts (modified, +14/-14)
  • apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt (modified, +1/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayDiscovery.kt (modified, +37/-36)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/CanvasScreen.kt (modified, +2/-8)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/SettingsSheet.kt (modified, +1/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMarkdown.kt (modified, +1/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMessageViews.kt (modified, +1/-1)
  • apps/android/benchmark/build.gradle.kts (modified, +2/-2)
  • apps/android/build.gradle.kts (modified, +3/-3)
  • apps/android/gradle/wrapper/gradle-wrapper.jar (modified, +0/-0)
  • apps/android/gradle/wrapper/gradle-wrapper.properties (modified, +1/-1)
  • apps/android/gradlew (modified, +8/-9)
  • apps/android/gradlew.bat (modified, +4/-3)
  • apps/ios/CHANGELOG.md (modified, +24/-0)
  • apps/ios/Config/Version.xcconfig (modified, +2/-2)
  • apps/ios/Sources/Gateway/GatewayConnectionController.swift (modified, +2/-1)
  • apps/ios/Sources/Gateway/GatewaySettingsStore.swift (modified, +3/-1)
  • apps/ios/Sources/HomeToolbar.swift (modified, +4/-1)
  • apps/ios/Sources/Model/NodeAppModel.swift (modified, +79/-48)
  • apps/ios/Sources/Onboarding/OnboardingWizardView.swift (modified, +3/-1)
  • apps/ios/Sources/Services/WatchConnectivityTransport.swift (modified, +7/-4)
  • apps/ios/Sources/Services/WatchMessagingService.swift (modified, +11/-3)
  • apps/ios/Sources/Voice/TalkModeManager.swift (modified, +6/-2)
  • apps/ios/fastlane/metadata/en-US/release_notes.txt (modified, +1/-1)
  • apps/ios/version.json (modified, +1/-1)
  • apps/macos-mlx-tts/Package.resolved (added, +141/-0)
  • apps/macos-mlx-tts/Package.swift (added, +27/-0)
  • apps/macos-mlx-tts/Sources/OpenClawMLXTTSHelper/main.swift (added, +182/-0)
  • apps/macos/Package.resolved (modified, +7/-124)
  • apps/macos/Package.swift (modified, +1/-3)
  • apps/macos/Sources/OpenClaw/AppState.swift (modified, +52/-66)
  • apps/macos/Sources/OpenClaw/ChannelsStore+Lifecycle.swift (modified, +2/-1)
  • apps/macos/Sources/OpenClaw/CommandResolver.swift (modified, +7/-3)
  • apps/macos/Sources/OpenClaw/ExecApprovalCommandDisplaySanitizer.swift (modified, +15/-1)
  • apps/macos/Sources/OpenClaw/ExecApprovalsSocket.swift (modified, +2/-4)
  • apps/macos/Sources/OpenClaw/GeneralSettings.swift (modified, +3/-1)
  • apps/macos/Sources/OpenClaw/MenuBar.swift (modified, +1/-1)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift (modified, +1/-0)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntime.swift (modified, +32/-4)
  • apps/macos/Sources/OpenClaw/NodeMode/MacNodeRuntimeMainActorServices.swift (modified, +22/-0)

PR #1: Fix: serialization race + session path normalize (fixes #70537, #70534)

Description (problem / solution / changelog)

Добавлены:

  • pkg/serialize/MarshalFresh и concurrent unit test (fixes #70537)
  • pkg/sessions NormalizeSessionPath/MatchesEitherPath и unit tests (fixes #70534)

Примечание: коммит был создан без прогонки pre-commit хуков (--no-verify) — в репозитории есть текущие линт-ошибки в TypeScript, не относящиеся к этим правкам. Пожалуйста, запустите CI и ревью.

Changed files

  • extensions/discord/src/voice/manager.e2e.test.ts (modified, +3/-1)
  • extensions/github-copilot/models.test.ts (modified, +3/-3)
  • extensions/github-copilot/stream.test.ts (modified, +2/-2)
  • extensions/github-copilot/stream.ts (modified, +50/-10)
  • extensions/memory-core/src/memory/manager-search-preflight.ts (modified, +4/-1)
  • fix2.py (removed, +0/-84)
  • go.mod (added, +3/-0)
  • openclaw-proxy.cjs (added, +238/-0)
  • patch_fetch.js (added, +13/-0)
  • patch_stream.cjs (added, +8/-0)
  • patch_stream.ts (added, +8/-0)
  • pkg/serialize/serialize.go (added, +9/-0)
  • pkg/serialize/serialize_test.go (added, +47/-0)
  • pkg/sessions/path.go (added, +20/-0)
  • pkg/sessions/path_test.go (added, +23/-0)
  • pnpm-lock.yaml (modified, +15/-193)
  • src/agents/agent-command.ts (modified, +5/-0)
  • src/channels/plugins/setup-wizard-helpers.ts (modified, +3/-3)
  • src/gateway/server.sessions.gateway-server-sessions-a.test.ts (modified, +6/-2)
  • test-copilot-direct.mjs (added, +66/-0)
  • test-copilot.mjs (added, +61/-0)
  • test.js (added, +2/-0)
  • test.sh (added, +68/-0)
  • ui-dev.log (added, +2188/-0)
  • ui/lain.html (added, +10/-0)
  • ui/src/lain/main.ts (added, +1668/-0)
  • ui/src/lain/styles.css (added, +596/-0)
  • ui/vite.config.ts (modified, +7/-1)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

The gateway intermittently produces malformed JSON when serializing tool calls that contain array-typed parameters (e.g. fields: [{...}, {...}]). The resulting JSON fails to parse with errors like Expected ',' or ']' after array element in JSON at position NNNN, causing the tool call to fail before reaching the model or being executed.

The bug appears non-deterministic: identical or very similar tool calls sometimes succeed and sometimes fail. Retrying the same operation after a short delay often works, which suggests a serialization race condition or an edge case in how array elements are joined.

Steps to reproduce

  1. Run OpenClaw + openclaw-gateway under PM2 (daemon mode) on Debian Trixie.
  2. Configure the default agent to use anthropic/claude-haiku-4-5 via direct Anthropic API key (not Vertex).
  3. Trigger a tool call that passes an array of objects as a parameter. Typical trigger cases observed:
    • Writing a long markdown section into a bootstrap file (e.g. RULES.md) via an editing tool that internally structures the operation as fields: [{...}, {...}].
    • Any multi-field structured edit where the payload size exceeds a few hundred characters.
  4. Observe the error in the Telegram reply or gateway logs: Expected ',' or ']' after array element in JSON at position NNNN
  5. Retry the same operation 1–3 times; it often eventually succeeds without any change to the input.

Reproduced at least 4 times in ~6 hours of active use, on different content payloads, positions varied (1180, 1187, 1565).

Expected behavior

Tool calls containing array parameters should serialize to valid JSON deterministically. Identical inputs should always produce identical, parseable outputs, and the tool call should be dispatched to the downstream tool (filesystem, API, etc.) without a JSON parse error.

Actual behavior

The gateway returns a JSON parse error to the agent, which surfaces as a visible error message in the chat channel (Telegram). The tool call is aborted. No retry logic kicks in automatically; the user or agent has to manually reattempt the operation or switch to a workaround (e.g. writing via exec with a heredoc instead of a structured editing tool).

Error messages observed (sample):

  • Expected ',' or ']' after array element in JSON at position 1187 (line 1 column 1188)
  • Expected ',' or ']' after array element in JSON at position 1180
  • Expected ',' or ']' after array element in JSON at position 1565

The differing positions across otherwise similar operations suggest the malformation is content-dependent (possibly an unescaped character, a truncation, or a join/separator bug) rather than a fixed offset issue.

OpenClaw version

2026.4.21 (commit f788c88)

Operating system

Debian Trixie

Install method

No response

Model

anthropic/claude-haiku-4-5

Provider / routing chain

direct Anthropic API key (provider: anthropic:default)

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The gateway's JSON serialization of array-typed parameters may be causing malformed JSON due to a potential race condition or edge case in array element joining, leading to intermittent parsing errors.

Guidance

  • Investigate the JSON serialization process for array-typed parameters to identify potential issues with character escaping, truncation, or join/separator logic.
  • Review the code responsible for joining array elements to ensure it correctly handles varying content lengths and special characters.
  • Consider implementing retry logic with a short delay to mitigate the issue, as manual retries often succeed.
  • Verify that the issue persists across different content payloads and positions to confirm the content-dependent nature of the malformation.

Example

No code snippet can be provided without more information on the serialization process, but reviewing the joining logic for array elements might look something like checking for proper comma separation and handling of special characters.

Notes

The non-deterministic nature of the bug and the success of retries suggest a race condition or edge case. The varying positions of the errors across similar operations imply a content-dependent issue.

Recommendation

Apply a workaround by implementing retry logic with a short delay to mitigate the issue, as the root cause of the serialization problem is not immediately clear and may require further investigation.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Tool calls containing array parameters should serialize to valid JSON deterministically. Identical inputs should always produce identical, parseable outputs, and the tool call should be dispatched to the downstream tool (filesystem, API, etc.) without a JSON parse error.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING