openclaw - 💡(How to fix) Fix [Bug] @mariozechner/pi-ai tool validation throws on empty args instead of returning tool_error — regression from 2026.3.22 [2 comments, 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#53671Fetched 2026-04-08 01:25:03
View on GitHub
Comments
2
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
commented ×2

Error Message

if (!validate(args)) { return { type: "tool_error", error: Validation failed: ... }; // instead of: throw new Error(...) }

Root Cause

2026.3.22 introduced @mariozechner/pi-ai as an external dependency. Its validateToolArguments() function uses AJV strict validation and throws on missing required fields:

// @mariozechner/pi-ai/dist/utils/validation.js (v0.61.1)
export function validateToolArguments(tool, toolCall) {
    const validate = ajv.compile(tool.parameters);
    const args = structuredClone(toolCall.arguments);
    if (validate(args)) return args;
    throw new Error(`Validation failed for tool "${toolCall.name}":\n...`);  // ← hard throw
}

In 2026.3.13, OpenClaw used its own bundled pi-ai with no AJV validation layer — empty args were passed through silently. The behavior change is a silent breaking change: models that already sent occasional empty tool calls now experience full turn failures instead of recoverable errors.

Fix Action

Temporary Workaround

Use tools.byProvider to deny problematic tools for affected providers:

{
  tools: {
    byProvider: {
      "kimi-coding": { deny: ["exec", "process"] },
      "kimi": { deny: ["exec", "process"] }
    }
  }
}

This prevents the validation from being reached, but removes exec functionality for these models entirely.

Code Example

// @mariozechner/pi-ai/dist/utils/validation.js (v0.61.1)
export function validateToolArguments(tool, toolCall) {
    const validate = ajv.compile(tool.parameters);
    const args = structuredClone(toolCall.arguments);
    if (validate(args)) return args;
    throw new Error(`Validation failed for tool "${toolCall.name}":\n...`);  // ← hard throw
}

---

Validation failed for tool "exec":
command: must have required property 'command'

Received arguments: {}

---

if (!validate(args)) {
    return { type: "tool_error", error: `Validation failed: ...` };
    // instead of: throw new Error(...)
}

---

{
  tools: {
    byProvider: {
      "kimi-coding": { deny: ["exec", "process"] },
      "kimi": { deny: ["exec", "process"] }
    }
  }
}

---

{
  models: {
    providers: {
      "kimi": {
        toolCallValidation: "warn"  // "strict" | "warn" | "off"
      }
    }
  }
}
RAW_BUFFERClick to expand / collapse

Problem Description

Since upgrading from 2026.3.13 → 2026.3.22, certain third-party models (confirmed: Moonshot AI kimi-latest via openai-completions, and kimi-coding/k2p5 via anthropic-messages) occasionally emit tool calls with empty arguments {} for the exec tool. This now causes a hard exception that terminates the entire agent turn, instead of being handled gracefully.

Root Cause

2026.3.22 introduced @mariozechner/pi-ai as an external dependency. Its validateToolArguments() function uses AJV strict validation and throws on missing required fields:

// @mariozechner/pi-ai/dist/utils/validation.js (v0.61.1)
export function validateToolArguments(tool, toolCall) {
    const validate = ajv.compile(tool.parameters);
    const args = structuredClone(toolCall.arguments);
    if (validate(args)) return args;
    throw new Error(`Validation failed for tool "${toolCall.name}":\n...`);  // ← hard throw
}

In 2026.3.13, OpenClaw used its own bundled pi-ai with no AJV validation layer — empty args were passed through silently. The behavior change is a silent breaking change: models that already sent occasional empty tool calls now experience full turn failures instead of recoverable errors.

Environment

  • OpenClaw version: 2026.3.23-2 (regression introduced in 2026.3.22)
  • @mariozechner/pi-ai version: 0.61.1
  • Affected models:
    • kimi/kimi-latest (provider api: openai-completions)
    • kimi-coding/k2p5 (provider api: anthropic-messages)
  • OS: macOS 25.3.0 (darwin arm64)

Observed Behavior

Validation failed for tool "exec":
command: must have required property 'command'

Received arguments: {}

This error is thrown as an uncaught exception, terminating the agent turn entirely. High frequency — occurs on most exec tool call attempts by these models.

Expected Behavior

Validation failures on tool call arguments should be handled gracefully as a tool_error result returned to the model, not a hard exception. This allows the model to recover (e.g., retry with correct arguments) rather than crashing the turn.

The equivalent behavior would be:

if (!validate(args)) {
    return { type: "tool_error", error: `Validation failed: ...` };
    // instead of: throw new Error(...)
}

Why This Matters

  • In 2026.3.13: empty {} args from model → silently passed through → recoverable downstream error
  • In 2026.3.22+: empty {} args from model → AJV throws → entire turn crashes

This affects any third-party model (especially those using openai-completions or anthropic-messages compat API) that doesn't always fill in required tool parameters perfectly. These models were working fine before 2026.3.22.

Temporary Workaround

Use tools.byProvider to deny problematic tools for affected providers:

{
  tools: {
    byProvider: {
      "kimi-coding": { deny: ["exec", "process"] },
      "kimi": { deny: ["exec", "process"] }
    }
  }
}

This prevents the validation from being reached, but removes exec functionality for these models entirely.

Suggested Fix

In @mariozechner/pi-ai (or in the OpenClaw wrapper that calls validateToolArguments): catch validation errors and return a structured tool_error to the model instead of throwing, so the agent turn can continue.

Alternatively, expose a per-provider config option to skip or soften tool argument validation:

{
  models: {
    providers: {
      "kimi": {
        toolCallValidation: "warn"  // "strict" | "warn" | "off"
      }
    }
  }
}

References

  • Related to the introduction of @mariozechner/pi-ai in 2026.3.22
  • @mariozechner/pi-ai validation code: /node_modules/@mariozechner/pi-ai/dist/utils/validation.js

extent analysis

Fix Plan

To address the issue, we need to modify the validateToolArguments function in @mariozechner/pi-ai to catch validation errors and return a structured tool_error instead of throwing an exception. Here are the steps:

  • Modify the validateToolArguments function to catch validation errors:
export function validateToolArguments(tool, toolCall) {
    const validate = ajv.compile(tool.parameters);
    const args = structuredClone(toolCall.arguments);
    try {
        if (validate(args)) return args;
    } catch (error) {
        return { type: "tool_error", error: `Validation failed for tool "${toolCall.name}": ${error.message}` };
    }
}
  • Alternatively, expose a per-provider config option to skip or soften tool argument validation. This can be done by adding a new option to the models.providers config:
{
  models: {
    providers: {
      "kimi": {
        toolCallValidation: "warn"  // "strict" | "warn" | "off"
      }
    }
  }
}

Then, modify the validateToolArguments function to respect this config option:

export function validateToolArguments(tool, toolCall, providerConfig) {
    const validate = ajv.compile(tool.parameters);
    const args = structuredClone(toolCall.arguments);
    if (providerConfig.toolCallValidation === "off") return args;
    try {
        if (validate(args)) return args;
    } catch (error) {
        if (providerConfig.toolCallValidation === "warn") {
            // log a warning instead of returning an error
            console.warn(`Validation failed for tool "${toolCall.name}": ${error.message}`);
            return args;
        } else {
            return { type: "tool_error", error: `Validation failed for tool "${toolCall.name}": ${error.message}` };
        }
    }
}

Verification

To verify that the fix worked, test the validateToolArguments function with different input scenarios, including:

  • Valid tool arguments
  • Invalid tool arguments (e.g. missing required fields)
  • Tool arguments with unknown fields
  • Tool arguments with invalid field types

Verify that the function returns the expected output for each scenario, including the structured tool_error object when validation fails.

Extra Tips

  • Make sure to update the @mariozechner/pi-ai version to the latest version that includes the modified validateToolArguments function.
  • Consider adding additional logging or monitoring to track validation errors and improve the overall robustness of the system.
  • If using the per-provider config option, make sure to document the available options and their effects on the system behavior.

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 - 💡(How to fix) Fix [Bug] @mariozechner/pi-ai tool validation throws on empty args instead of returning tool_error — regression from 2026.3.22 [2 comments, 1 participants]