[Regression 2.1.265] Built-in Artifact database tool ships JSON-Schema `pattern` with `\p{...}` escapes — strict validators reject every request (400, "not a regex")

Status Open
Reported on v2.1.265
Maintainer reply None cached
Activity 1 comment · opened Sep 9, 2026

Summary

Regression in 2.1.265, still present in 2.1.266: the built-in Artifact database tool's input_schema gained a JSON-Schema pattern on its collection / document identifier fields that uses Unicode property escapes (\p{...}). Endpoints whose schema validators implement a strict regex subset reject the entire request with 400 Invalid JSON schema: ... is not a "regex". The pattern is valid ECMA-262 (with the u flag) and is accepted by Anthropic's own API, so first-party use never sees this — but any strict-validator-compatible endpoint fails every request carrying the tool. Because the tool ships in every request, the first turn fails and the session is fully unusable regardless of user input.

The offending pattern:

^(?!__.*__$)[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}"\\./[\]]{1,200}$

(intent: reject dunder-wrapped identifiers, control/format/separator characters, " \ . / [ ], cap at 200 chars.)

Repro

  1. Run Claude Code 2.1.265 (or 2.1.266) with requests routed to a third-party Anthropic-compatible endpoint whose JSON-Schema validator does not support Unicode property escapes (\p{...}).
  2. Start an interactive session and send any prompt.
  3. The first turn fails deterministically, e.g.:
API Error: 400 Invalid JSON schema: "^(?!__.*__$)[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}\"\\\\./[\\]]{1,200}$" is not a "regex"

(exact error wording varies by gateway; the invariant is a 400-class schema rejection naming that pattern.)

Control: the identical session shape on 2.1.263 succeeds with zero schema errors.

Minimal wire repro: send any /v1/messages request carrying the built-in Artifact database tool schema exactly as shipped → 400. Re-send with only the two identifier pattern keywords (collection / document id) stripped → accepted. No other change needed.

Expected vs Actual

  • Expected: the shipped tool schemas validate on any spec-conformant Anthropic-compatible endpoint; an identifier-validation refinement never bricks sessions on strict validators.
  • Actual (2.1.265 / 2.1.266): every request carrying the Artifact database tool is rejected by strict validators before inference, so the session fails on turn one for any input. 2.1.263 (no such pattern) works.

Root cause (with evidence)

Binary forensics of the linux-x64 harness tarballs:

  • 2.1.263: the entire validation block is absent — no such pattern anywhere in the binary.
  • 2.1.265: the string appears twice:
  1. once as a JS validator with the u flag — /^(?!__.*__$)[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}"\\./[\]]{1,200}$/u — in the Artifact database tool code, adjacent to the get / list / query and set / update / delete db_op handling;
  2. once as a bare string in a validation/spec table, consistent with wire emission as the JSON-Schema pattern for the collection / document identifier fields.
  • 2.1.266 (npm next tag): present byte-identical — not fixed.

So the regression is the introduction (in 2.1.265) of a \p{...}-dependent pattern that is both enforced locally (JS, where /u makes it legal) and emitted on the wire (JSON Schema, where the receiving validator's regex dialect governs). Strict validators that don't implement Unicode property escapes reject the schema itself, hence the deterministic first-turn 400 on any session carrying the tool.

Suggested fix

In order of preference:

  1. (Recommended, cleanest) Rewrite the segment pattern without \p{...} using explicit code-point ranges. The validation intent is fully expressible in portable syntax, e.g. \p{Cc}U+0000–U+001F, U+007F–U+009F; \p{Zl}U+2028; \p{Zp}U+2029; \p{Cf} → the explicit Cf list generated from the project's pinned Unicode version (its membership is version-dependent, so generate it programmatically rather than hand-transcribing). This keeps the client-side guardrail and maximizes validator compatibility, with zero endpoint-sniffing.
  2. Drop pattern from those fields. Safe if server-side validation is already authoritative (the client pattern is then defense-in-depth / early UX feedback). Cheapest, but loses the early client-side rejection the pattern was presumably added for.
  3. Withhold pattern on non-first-party endpoints. Works around the failure but introduces base-URL sniffing (fragile behind proxies / localhost / custom gateways) and schema drift between endpoints. Prefer a uniform portable schema (option 1) over endpoint-conditional schemas.

Verification for whichever is chosen: assert in CI that every shipped built-in tool pattern compiles under both a full ECMA-262-with-u engine and a strict-subset engine without \p{...} support (e.g. RE2 or equivalent), so no future pattern reintroduces the class.

Edge cases considered

  • Other tools may carry \p{...} too. The fix should audit all shipped input_schema patterns, not just the two Artifact identifier fields — one portable-pattern policy for every built-in tool, with the CI assertion above locking it.
  • ECMA-262-full vs strict-subset validators. The pattern is legal input (Anthropic accepts it); the failure is a dialect gap. Target the lowest common denominator: portable syntax that is simultaneously valid ECMA-262 and valid under strict subsets, with no flag dependence (the rewritten pattern must not rely on /u semantics to mean what it means).
  • Drop vs rewrite. Dropping is a contract change for anyone validating identifiers locally against the shipped schema; rewriting preserves the documented intent (dunder guard, excluded characters, 200-char cap) while restoring compatibility — which is why option 1 is recommended.
  • Backward compatibility of stored identifiers. Identifiers created under the pattern-less schema (≤ 2.1.263) already exist; the read paths (get / list / query) must not retroactively reject them, and the rewritten pattern's accept-set must match the server-side rules exactly (including the dunder guard and the 200 limit) or previously-valid reads break.
  • Length semantics and astral-plane input. Keep the 200-unit semantics identical through the rewrite (UTF-16 code units vs scalar values vs bytes must not silently change); cover combining marks, U+FEFF / U+200B-style Cf edge cases, and supplementary-plane identifiers in tests.
  • Single-tool blast radius. A schema-level rejection of one tool's pattern fails the whole request, not just calls to that tool — so any non-portable construct anywhere in the always-shipped tool set is session-fatal. That's what makes this class worth a registry-wide CI gate rather than a one-spot fix.

Environment

  • Claude Code 2.1.265 (regressed) and 2.1.266 (still present, byte-identical); last working 2.1.263.
  • Platform observed: linux-x64 harness build; failure is endpoint-determined, not OS-specific.
  • Endpoint: third-party Anthropic-compatible /v1/messages endpoint with a strict JSON-Schema validator (no \p{...} support). First-party Anthropic API accepts the schema (valid ECMA-262 with u).

Related

  • #92964 — closest neighbor: same pattern, same version bracket, bisected from the request-body side (interactive fails, stripped-pattern replay succeeds). This filing adds the binary-side root cause (dual occurrence: JS /u validator + wire-emitted spec-table string; absent in 2.1.263, byte-identical in 2.1.266) and the portable-rewrite recommendation with edge cases.
  • #92900 — nearby in symptom space (tool schemas breaking sessions) but a different defect (boolean property schemas in MCP tool conversion, SDK-side tool dropping — silent, partial). Mentioning only to aid triage; not the same bug.
  • #84056 — interactive-only 400s from input_schema keywords on strict backends (MCP oneOf/allOf/anyOf); same failure class (schema-dialect gap bricks the whole request), different construct.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗