openclaw - ✅(Solved) Fix [Bug]: Tool call infinite loop on validation failure — null params bypass loopDetection [3 pull requests, 1 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#72587Fetched 2026-04-28 06:34:11
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×3closed ×1referenced ×1

When a model (Claude Opus 4.6 in our case) serializes tool arguments as null instead of {} for a parameterless tool, OpenClaw returns a validation error (root: must be object) but does not trigger loopDetection. The model retries with null again, creating an infinite validation-failure loop.

In our case, wiki_lint was called dozens of times consecutively, each time with null arguments, each time returning the same validation error. The loop ran unchecked until the user manually intervened.

Error Message

When a model (Claude Opus 4.6 in our case) serializes tool arguments as null instead of {} for a parameterless tool, OpenClaw returns a validation error (root: must be object) but does not trigger loopDetection. The model retries with null again, creating an infinite validation-failure loop. In our case, wiki_lint was called dozens of times consecutively, each time with null arguments, each time returning the same validation error. The loop ran unchecked until the user manually intervened. This exact error repeated dozens of times in a single turn with no circuit breaker. 2. Missing validation-error loop detection (defense in depth)

Root Cause

When a model (Claude Opus 4.6 in our case) serializes tool arguments as null instead of {} for a parameterless tool, OpenClaw returns a validation error (root: must be object) but does not trigger loopDetection. The model retries with null again, creating an infinite validation-failure loop.

In our case, wiki_lint was called dozens of times consecutively, each time with null arguments, each time returning the same validation error. The loop ran unchecked until the user manually intervened.

Fix Action

Fixed

PR fix notes

PR #72628: Fix: issue 72587 null tool params

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

If this PR fixes a plugin beta-release blocker, title it fix(<plugin-id>): beta blocker - <summary> and link the matching Beta blocker: <plugin-name> - <summary> issue labeled beta-blocker. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation.

  • Problem: Parameterless object-schema tools like wiki_lint could fail before execution when a provider emitted null tool arguments.
  • Why it matters: The model could repeatedly retry the same invalid call because Pi validates arguments before OpenClaw’s tool execution hook can run.
  • What changed: toToolDefinitions now adds a narrow prepareArguments shim that converts null/undefined to {} only for object schemas with no required fields.
  • What did NOT change (scope boundary): Required-parameter tools, loop-detection defaults, provider parsing, and wiki_lint’s schema were not changed.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #72587
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: Pi validates tool arguments before OpenClaw’s execution hook, and Type.Object({}) rejects null even for parameterless tools.
  • Missing detection / guardrail: Server-side tool definition adaptation had no regression test for null args on parameterless object-schema tools.
  • Contributing context (if known): Some providers serialize parameterless tool arguments as null instead of {}.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
    • Target test or file: src/agents/pi-tool-definition-adapter.test.ts
    • Scenario the test should lock in: Parameterless object-schema tools prepare null as {}, while required object-schema tools do not get this normalization.
    • Why this is the smallest reliable guardrail: The bug is in tool definition adaptation before Pi validation, so adapter-level coverage directly targets the boundary.
    • Existing test that already covers this (if any): None for server-side parameterless tool definitions.
    • If no new test is added, why not: N/A

User-visible / Behavior Changes

Parameterless tools can now run when a provider emits null args instead of {}. No config/default changes.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

  Before:
  model emits wiki_lint(null) -> Pi schema validation fails -> tool does not execute

  After:
  model emits wiki_lint(null) -> prepareArguments converts to {} -> Pi validation passes -> tool executes

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (Yes)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: Parameterless tools may now execute when the provider sends null instead of {}. The mitigation is narrow schema gating: only object schemas with no required fields receive this normalization; required-parameter tools remain unchanged.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local Node/pnpm checkout
  • Model/provider: Reproduced at dependency boundary with @mariozechner/pi-ai
  • Integration/channel (if any): Issue reported Telegram/Anthropic; local verification used the tool validation path
  • Relevant config (redacted): N/A

Steps

  1. Validate wiki_lint-style Type.Object({}, { additionalProperties: false }) with arguments: null.
  2. Confirm pre-fix validation fails with root: must be object.
  3. Confirm post-fix adapter prepares null as {} for parameterless object-schema tools.

Expected

  • Parameterless object-schema tools accept provider-emitted null as {}.

Actual

  • Before this fix, validation failed before tool execution.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • null validation failure reproduced before the fix.
    • Adapter test passes after adding prepareArguments.
    • Required object-schema tools do not get null normalization.
    • Plain object args pass through unchanged.
  • Edge cases checked:
    • null/undefined only normalize for no-required object schemas.
    • Required object-schema tools keep validation behavior.
  • What you did not verify:
    • Live Telegram/Anthropic channel run.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: A malformed null call could now execute a parameterless tool.
    • Mitigation: The normalization is limited to object schemas with no required fields, which are already designed to be called without user-supplied parameters.

Built with Codex

Changed files

  • src/agents/pi-tool-definition-adapter.test.ts (modified, +65/-0)
  • src/agents/pi-tool-definition-adapter.ts (modified, +31/-0)
  • src/plugins/cli-registry-loader.ts (modified, +25/-1)
  • src/plugins/cli.test.ts (modified, +87/-0)

PR #72634: fix: normalize null params to {} for empty object schemas (prevents infinite loops)

Description (problem / solution / changelog)

Summary

Fixes infinite validation-failure loops when models send null for optional object parameters (Issue #72587).

Problem

When models send null as tool parameters for tools with empty object schemas (e.g., wiki_lint), validation fails with "root: must be object" error. The model retries with null again, creating an infinite validation-failure loop because loop detection doesn't catch these repeated validation errors.

Solution

Added parameter normalization that converts null{} for tools with empty object schemas, allowing them to execute successfully while maintaining loop detection.

Changes

  • Added normalizeToolParams() function
    Converts null to {} for tools with:

    • Schema type: "object"
    • No required properties
    • No properties defined
  • Modified wrapToolWithBeforeToolCallHook()
    Applies normalization before tool execution, using normalized params for:

    • Event emission
    • Tool execution
    • Loop outcome recording
    • Parameter summaries
  • Exported for testing
    Added normalizeToolParams to __testing exports

Impact

Benefits

✅ Prevents infinite loops from repeated validation failures
✅ Graceful handling of null params for tools with optional parameters
✅ Backward compatible (only affects cases where null was already failing)
✅ Type-safe implementation

Affected Tools

Tools with empty object schemas:

  • wiki_lint
  • wiki_status
  • Any similar tools registered by plugins

Testing

All 79 existing tests pass:

  • pi-tools.before-tool-call.e2e.test.ts - 34 tests ✓
  • pi-tools.before-tool-call.embedded-mode.test.ts - 4 tests ✓
  • tool-loop-detection.test.ts - 31 tests ✓
  • pi-tools.params.test.ts - 10 tests ✓

Manual verification:

  • ✅ Null params normalized to {} for empty object schemas
  • ✅ Tools execute successfully with normalized params
  • ✅ Loop detection tracks execution
  • ✅ No infinite loops occur

Files Changed

 src/agents/pi-tools.before-tool-call.ts | 49 +++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 6 deletions(-)

Example

Before:
Model sends null → Validation fails → Model retries null → Infinite loop ❌

After:
Model sends null → Normalized to {} → Tool executes → Loop detected if repeated ✅


Closes #72587

Labels to Add:

  • bug
  • fix

Changed files

  • src/agents/pi-tools.before-tool-call.ts (modified, +43/-6)

PR #72673: Fix null params for parameterless tools

Description (problem / solution / changelog)

Summary

  • Normalize null or missing tool arguments to {} for root object schemas that have no required parameters.
  • Preserve validation failures for object schemas that still require parameters.
  • Add a regression that drives the real pi-agent loop with a wiki_lint-style tool call whose arguments are null.

Root Cause

The upstream pi-agent loop validates tool arguments before invoking OpenClaw's wrapped execute handler. When a model serialized an empty argument object as null, parameterless object-schema tools failed validation before OpenClaw's loop/outcome tracking could observe execution. The existing prepareArguments seam runs before that validation step, so OpenClaw now uses it for schemas where {} is valid.

Fixes #72587

Validation

  • pnpm test src/agents/pi-tools.schema.test.ts
  • Mutation check: temporarily removed the fix and confirmed the new regression fails before restoring it.
  • pnpm exec oxfmt --check --threads=1 src/agents/pi-tools.schema.ts src/agents/pi-tools.schema.test.ts
  • pnpm check:changed

Changed files

  • src/agents/pi-tools.schema.test.ts (modified, +190/-0)
  • src/agents/pi-tools.schema.ts (modified, +54/-1)

Code Example

Tool output wiki_lint
Validation failed for tool "wiki_lint":
  - root: must be object

Received arguments:
null
RAW_BUFFERClick to expand / collapse

Summary

When a model (Claude Opus 4.6 in our case) serializes tool arguments as null instead of {} for a parameterless tool, OpenClaw returns a validation error (root: must be object) but does not trigger loopDetection. The model retries with null again, creating an infinite validation-failure loop.

In our case, wiki_lint was called dozens of times consecutively, each time with null arguments, each time returning the same validation error. The loop ran unchecked until the user manually intervened.

Environment

  • OpenClaw version: 2026.4.23 (a979721)
  • Model: myclaw/claude-opus-4.6 (anthropic-messages provider)
  • Channel: Telegram (direct)
  • Tool: wiki_lint (schema: type: object, no required params)

Steps to Reproduce

  1. Use a model that occasionally serializes empty tool params as null (observed with Claude Opus 4.6)
  2. Have a tool with type: object schema and no required parameters (e.g. wiki_lint)
  3. Trigger the tool call in a context where the model keeps retrying after validation failure

Observed Behavior

⚡ Tool output wiki_lint
Validation failed for tool "wiki_lint":
  - root: must be object

Received arguments:
null

This exact error repeated dozens of times in a single turn with no circuit breaker.

Expected Behavior

Two defensive layers should prevent this:

  1. Parameter normalization: When a tool schema is type: object with no required params, and the model sends null, the runtime should auto-correct to {} instead of failing validation. This is a trivial defensive fix.

  2. Loop detection on validation failures: Repeated identical validation errors on the same tool should trigger the existing loopDetection mechanism. Currently, loopDetection only monitors successful tool calls with identical results, not repeated validation failures.

Related Issues

  • #34574 — loopDetection does not catch repeated exec tool calls (Open, unfixed, PR #34687 never merged)
  • #48947 — 200000 tool calls, no feedback, interruptions (Open, no fix plan)
  • #70872 — params: must be object for MCP tools passing params as string (Closed, but only fixed string→object, not null→object)

Additional Context

The model's system prompt (AGENTS.md) explicitly instructs: "After two consecutive same-class tool errors, stop and switch strategy." However, when the model enters this failure loop, it does not follow prompt-level instructions — reinforcing that runtime-level protection is necessary and prompt-level guards are insufficient.

This is a compound failure of:

  1. Missing null→{} normalization (easy fix)
  2. Missing validation-error loop detection (defense in depth)
  3. Model-side prompt compliance failure (not fixable by OpenClaw, but should not be relied upon)

extent analysis

TL;DR

Implementing null-to-object normalization for tool arguments and enhancing loop detection to include validation failures can prevent infinite validation-failure loops.

Guidance

  • Verify if the model's serialization of tool arguments as null instead of {} for parameterless tools is the primary cause of the issue.
  • Check the OpenClaw version and the model used to see if there are any known issues or fixes related to null-to-object normalization and loop detection.
  • Consider implementing a temporary workaround to detect and prevent repeated validation errors for the same tool, such as keeping track of recent validation failures and stopping the loop after a certain threshold.
  • Review the model's system prompt and ensure that it is correctly implemented to stop and switch strategy after two consecutive same-class tool errors.

Example

# Pseudo-code example of null-to-object normalization
def normalize_tool_args(args):
    if args is None:
        return {}
    return args

Notes

The provided solution assumes that the issue is primarily caused by the missing null-to-object normalization and loop detection. However, the model-side prompt compliance failure is also a contributing factor, which may require separate attention.

Recommendation

Apply a workaround to implement null-to-object normalization and enhance loop detection to include validation failures, as upgrading to a fixed version is not explicitly mentioned in the issue. This will help prevent infinite validation-failure loops and provide a more robust solution.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Tool call infinite loop on validation failure — null params bypass loopDetection [3 pull requests, 1 participants]