openclaw - ✅(Solved) Fix [Bug]: Browser tools fail with AJV "no schema with key or ref" 2020-12 error [1 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

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#58560Fetched 2026-04-08 02:01:05
View on GitHub
Comments
1
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
labeled ×2

All browser tools (browser_navigate, browser_run_code, browser_click, etc.) fail with a JSON Schema validation error. The error occurs at the parameter validation stage before the tool executes. Non-browser tools (peekaboo, etc.) work normally.

Error Message (exact) Error: no schema with key or ref "https://json-schema.org/draft/2020-12/schema"

Error Message

All browser tools (browser_navigate, browser_run_code, browser_click, etc.) fail with a JSON Schema validation error. The error occurs at the parameter validation stage before the tool executes. Non-browser tools (peekaboo, etc.) work normally. Error Message (exact) Error: no schema with key or ref "https://json-schema.org/draft/2020-12/schema" Browser tool call fails immediately with the schema validation error When AJV tries to validate/compile a schema containing the 2020-12 $schema URI, it cannot resolve the meta-schema and throws the error.

Root Cause

Root Cause Analysis We traced the issue to the following:

PR fix notes

PR #66137: fix(ajv): validate MCP tool schemas against draft/2020-12 [AI-assisted]

Description (problem / solution / changelog)

Summary

Fixes the no schema with key or ref "https://json-schema.org/draft/2020-12/schema" family of errors reported across browser tools and external MCP servers. There are four Ajv compile sites that need draft/2020-12 support; three are in openclaw source, the fourth is in a pinned dep:

  1. src/gateway/protocol/index.ts — gateway protocol schemas
  2. src/plugins/schema-validator.ts — plugin config + channel schemas (validateJsonSchemaValue)
  3. extensions/llm-task/src/llm-task-tool.ts — user-supplied LLM output schema
  4. @mariozechner/pi-ai/dist/utils/validation.js — per-call validateToolArguments, runs for every tool invocation through @mariozechner/pi-agent-core's agent loop

All four migrate from default ajv (draft-07-only meta) to ajv/dist/2020.js with addMetaSchema(draft-07) so both dialects compile. The fourth site is covered two ways: a pnpm patch on @mariozechner/[email protected] (so source builds and pnpm installs are correct), and an in-place hotfix in scripts/postinstall-bundled-plugins.mjs (so npm i -g openclaw@latest users — who don't honor pnpm.patchedDependencies — also get the fix; pi-ai is not bundled into openclaw's dist/, so without the postinstall hook the patch wouldn't ship to production at all). The hotfix follows the existing baileys pattern: atomic write, mode preservation, path-escape guards, marker-based idempotency.

Why this path (research summary)

  1. Traced the user-visible error from the Python MCP server: pydantic v2's GenerateJsonSchema.schema_dialect emits $schema: "https://json-schema.org/draft/2020-12/schema" on every inputSchema. Same story for zod-emitted browser/playwright tool schemas (target: "draft-2020-12").
  2. Verified empirically: default Ajv throws no schema with key or ref "https://json-schema.org/draft/2020-12/schema" at compile, regardless of strict: false (which only silences unknown-keyword warnings — it does not suppress $schema URI resolution).
  3. Rejected the inverse (default Ajv + addMetaSchema(draft-2020-12)): the 2020-12 meta is multi-file and throws MissingRefError: can't resolve reference meta/core; even if patched around, default Ajv silently ignores 2020-12-only keywords (prefixItems, unevaluatedProperties, $dynamicRef) under strict: false — which is the same silent-correctness bug, reframed.
  4. Ajv2020 + addMetaSchema(draft-07) is the correct direction. Ajv2020 implements every draft-07 keyword in use (dependencies verified to produce the exact keyword: 'dependencies' / params.missingProperty shape schema-validator.ts:98 consumes; definitions, $defs, object/string/number constraints all identical). The one draft-07 shape Ajv2020 hard-rejects — tuple items: [...] — was grep-confirmed absent from every internal schema fed into Ajv across src/, extensions/, and the 486 KB bundled-channel-config-metadata.generated.ts. additionalItems, $recursiveRef, $recursiveAnchor likewise absent. If a contributor ever introduces tuple items, Ajv2020 fails loudly (items value must be ["object","boolean"]) rather than silently miscompiling — strictly safer.
  5. The fourth site (pi-ai) is the actual hot path — validateToolArguments runs on every tool call. #65798's reporter applied the openclaw-side fix manually and saw "improved but not eliminated" because the per-tool-call validator inside the pinned dep was still default Ajv. Tracing from src/agents/pi-bundle-mcp-materialize.ts:104 (parameters: tool.inputSchema) into pi-agent-core's agent-loop.js:301 led to pi-ai/dist/utils/validation.js; both the pnpm patch and the postinstall hotfix exist to cover the same site across both install paths.
  6. Considered and rejected per-$schema dispatch in llm-task: tried it, then realized any unlabeled-default choice has a failure mode (Ajv2020-default loud-fails on tuple items; draft-07-default silently miscompiles 2020-12-only keywords on unlabeled MCP schemas — re-introducing the original bug). Reverted; single-instance Ajv2020 + draft-07 meta is the only design without a dialect-routing footgun. (Discussion lives in the resolved P2 review threads.)

Closes #58560 Closes #61863 Closes #65798

Note: #58084 is not closed by this PR. That's an emission-side issue — Anthropic's draft/2020-12 validator rejects schemas openclaw sends (likely anchored patternProperties or TypeBox tuple items). The fix belongs in src/agents/pi-tools.schema.ts / src/agents/pi-embedded-runner/anthropic-family-tool-payload-compat.ts, not here.

Test plan

  • pnpm tsgo — no new type errors; pre-existing failures in telegram/whatsapp/cron/wizard reproduce on clean main via git stash
  • pnpm build:plugin-sdk:dts — succeeds (ajv/dist/2020.js specifier required for NodeNext; [email protected] has no exports map)
  • pnpm test -- src/plugins/schema-validator.test.ts src/gateway/protocol/*.test.ts src/secrets/exec-secret-ref-id-parity.test.ts — 55 green
  • pnpm test -- src/mcp/plugin-tools-serve.test.ts src/gateway/mcp-http.test.ts extensions/memory-wiki/src/config.test.ts — green
  • Empirical: real draft-07 schema from bundled-channel-config-metadata.generated.ts compiles/validates correctly; draft/2020-12 schema with unevaluatedProperties: false correctly rejects extras
  • Empirical on the patched pi-ai: validateToolCall accepts both draft-07 and draft/2020-12 tools, including 2020-12 unevaluatedProperties rejection
  • Postinstall hotfix idempotency: simulated unpatched input → applied; rerun → already_patched; restore → clean
  • Live production smoke-test: built openclaw-2026.4.14.tgz from this branch (pnpm install && pnpm build && pnpm ui:build && OPENCLAW_PREPACK_PREPARED=1 pnpm pack), installed on the author's production server via npm i -g ./openclaw-2026.4.14.tgz, confirmed the postinstall hotfix applied (@mariozechner/pi-ai/dist/utils/validation.js now imports ajv/dist/2020.js and registers the draft-07 meta-schema), and verified the fix works against a real MCP surface — tool invocations that previously threw no schema with key or ref "https://json-schema.org/draft/2020-12/schema" now succeed.
  • extensions/diffs/src/config.test.ts viewer-asset failures, src/agents/pi-bundle-mcp-runtime.test.ts MCP-process flakes, and llm-task Windows mkdtemp failures all verified pre-existing on clean main

CI status (red checks pre-exist on main)

CI is mostly green: 29 passing, 6 skipping, 6 failing. The 6 failing jobs are pre-existing failures on main or PR-required-by-design comparisons — none caused by this PR. Per CONTRIBUTING.md lines 116–117, these aren't ours to fix.

Failing jobStatus on mainNotes
check-additionalfailing on latest main (95cdaf957b) and 4 of last 5 main runslint targets no-monolithic-plugin-sdk-entry-imports, no-extension-test-core-imports — neither path touched by this PR
checks-fast-contracts-protocolfailing on latest main and 4 of last 5src/plugins/contracts/provider-family-plugin-tests.test.ts:241 provider-family snapshot — not touched
checks-node-core-fastfailing on latest main and 5 of last 5test/openclaw-npm-release-check.test.ts:282 missing docs templates (AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md) — not touched
checks-node-corefailing on latest main and 5 of last 5same surface as above
checks-node-agenticintermittent on main; failing in 4 of last 5src/agents/minimax-docs.test.tsUnable to resolve bundled plugin public surface minimax/api.js — not touched
Run the GPT-5.4 / Opus 4.6 parity gate against the qa-lab mocknot run on main (PR-only by design)model-output parity comparison; verdict comes from the model comparison, not from openclaw code

All Ajv- and pi-ai-touching jobs pass: check, build-artifacts, build-smoke, checks-node-core-src, checks-node-core-security, checks-node-extensions-shard-1..6, extension-fast-llm-task, install-smoke, security-fast, actionlint, no-tabs, etc.

AI-assisted

  • Mark as AI-assisted: yes (Claude Code / Opus 4.6)
  • Degree of testing: fully tested end-to-end — typecheck, targeted vitest, empirical Ajv checks through the pi-ai entrypoint against both dialects, postinstall hotfix idempotency simulation, and a live production smoke-test on the author's npm-installed server (see Test plan).
  • I understand the code: yes — four-site Ajv2020 + addMetaSchema(draft-07) migration; pi-ai vendored dep covered via pnpm patch and postinstall string-replace hotfix to bridge the npm-install gap; rationale and tradeoffs above.
  • Session logs: available on request.
  • All five codex-connector review threads on this PR have been replied to and resolved.

Changed files

  • extensions/llm-task/src/llm-task-tool.ts (modified, +9/-1)
  • package.json (modified, +2/-1)
  • patches/@[email protected] (added, +22/-0)
  • pnpm-lock.yaml (modified, +7/-4)
  • scripts/postinstall-bundled-plugins.mjs (modified, +140/-3)
  • src/gateway/protocol/index.ts (modified, +12/-1)
  • src/plugins/schema-validator.ts (modified, +8/-1)
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

All browser tools (browser_navigate, browser_run_code, browser_click, etc.) fail with a JSON Schema validation error. The error occurs at the parameter validation stage before the tool executes. Non-browser tools (peekaboo, etc.) work normally.

Error Message (exact) Error: no schema with key or ref "https://json-schema.org/draft/2020-12/schema"

Steps to reproduce

Install OpenClaw via npm install -g openclaw Configure any channel (Telegram in our case) with any supported model Ask the agent to navigate to any URL (e.g., "open google.com") Browser tool call fails immediately with the schema validation error

Reproduction rate: 100%

Expected behavior

Browser tools should work without schema validation errors. Either:

Use Ajv2020 class instead of base Ajv when schemas use draft-2020-12, or Strip $schema key from generated tool schemas before passing to AJV, or Register the 2020-12 meta-schema on the base Ajv instance via addMetaSchema()

Actual behavior

<img width="569" height="467" alt="Image" src="https://github.com/user-attachments/assets/9bc104b2-fcdd-4544-b083-c23e40718e27" />

OpenClaw version

OpenClaw version: 2026.3.24 / 2026.3.28 (tested both)

Operating system

OS: macOS (arm64, Apple Silicon)

Install method

npm global via Homebrew

Model

sonnet 4.6

Provider / routing chain

OpenClaw Gateway

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

<img width="573" height="479" alt="Image" src="https://github.com/user-attachments/assets/16fd0352-f0f3-4382-8997-c03d0a7f6936" />

Additional information

The ajv package installed under OpenClaw's node_modules includes dist/2020.js, so the fix should be straightforward. This may be related to other schema validation issues: #22278, #14998, #18635, #29416.

Root Cause Analysis We traced the issue to the following:

Zod generates tool schemas with target: "draft-2020-12", which inserts "$schema": "https://json-schema.org/draft/2020-12/schema" into the generated JSON Schema objects. AJV instances are created with the base Ajv class (via require("ajv") / new AjvPkg({})), which only supports up to draft-07. Draft-2020-12 requires the Ajv2020 class from ajv/dist/2020. When AJV tries to validate/compile a schema containing the 2020-12 $schema URI, it cannot resolve the meta-schema and throws the error.

Key locations in dist bundle (v2026.3.28):

auth-profiles-B5ypC5S-.js line ~2121: getAjv(mode) function uses require$1("ajv") (base Ajv, not Ajv2020) auth-profiles-B5ypC5S-.js line ~335086: $schema: z.string().optional() — Zod schema definition method-scopes-DgElWZYI.js line ~1919: const ajv = new AjvPkg({}) — base Ajv instantiation extensions/llm-task/index.js line ~114: new AjvCtor({}) — another base Ajv instantiation ajv/dist/2020.js exists in node_modules/ajv/dist/ but is never imported

extent analysis

TL;DR

The most likely fix is to use the Ajv2020 class instead of the base Ajv class when validating schemas that use draft-2020-12.

Guidance

  • Identify all locations where the Ajv class is instantiated and replace it with the Ajv2020 class from the ajv/dist/2020 module.
  • Verify that the ajv/dist/2020.js file is being imported and used correctly in the code.
  • Check for any other schema validation issues that may be related to the use of the base Ajv class.
  • Consider registering the 2020-12 meta-schema on the base Ajv instance via addMetaSchema() as an alternative solution.

Example

// Before
const Ajv = require("ajv");
const ajv = new Ajv({});

// After
const Ajv2020 = require("ajv/dist/2020");
const ajv = new Ajv2020({});

Notes

The fix should be straightforward since the ajv package installed under OpenClaw's node_modules includes dist/2020.js. However, it's essential to verify that the Ajv2020 class is being used correctly and that there are no other schema validation issues.

Recommendation

Apply workaround: Use the Ajv2020 class instead of the base Ajv class when validating schemas that use draft-2020-12. This is because the base Ajv class only supports up to draft-07, and using the Ajv2020 class will provide support for draft-2020-12.

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

Browser tools should work without schema validation errors. Either:

Use Ajv2020 class instead of base Ajv when schemas use draft-2020-12, or Strip $schema key from generated tool schemas before passing to AJV, or Register the 2020-12 meta-schema on the base Ajv instance via addMetaSchema()

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]: Browser tools fail with AJV "no schema with key or ref" 2020-12 error [1 pull requests, 1 comments, 1 participants]