JuliusBrussee/caveman · error · Error
middleware
Error message
middleware ${field}: ${ajv.errorsText(validate?.errors)} What it means
The validator loads sdk/parity/middleware.fixtures.json and validates its `capabilities`, `request` (against the optimize schema), `plan`, and `page` fields against the compiled middleware-*.schema.json schemas via AJV. If a field is missing from the fixture, fails its schema, or the named schema was not compiled/registered (validate is undefined), it throws `middleware <field>: <errorsText>` (or "undefined" when validate is undefined). This keeps the SDK middleware parity fixtures aligned with the wire schemas.
Solutions
- Read the error text: the field name tells you which fixture section failed, and errorsText lists the exact AJV violations (path, keyword, expected value).
- Fix the offending value in sdk/parity/middleware.fixtures.json to satisfy packages/shared/contracts/schemas/middleware-<name>.schema.json.
- If validate?.errors is undefined, the schema lookup failed: verify the schema file exists, its $id matches https://caveman.so/schemas/middleware-<schemaName>.schema.json, and it compiles.
- If the fixture legitimately models new behavior, update the schema first (bump version if it's a breaking wire change), then regenerate the fixture.
- Ensure schemas and fixtures are updated in the same commit so they cannot drift.
Example fix
// before (middleware.fixtures.json)
"plan": { "transformIds": ["caveman.cache-preserve.v1"] }
// after (schema uses snake_case ids)
"plan": { "ordered_transform_ids": ["caveman.cache-preserve.v1"] } Defensive patterns
Strategy: validation
Validate before calling
import Ajv2020 from "ajv/dist/2020.js";
const ajv = new Ajv2020({ allErrors: true, strict: true });
ajv.addSchema(schemas);
const middleware = JSON.parse(await readFile("sdk/parity/middleware.fixtures.json", "utf8"));
for (const [field, name] of Object.entries({ capabilities: "capabilities", request: "optimize", plan: "plan", page: "page" })) {
const v = ajv.getSchema(`https://caveman.so/schemas/middleware-${name}.schema.json`);
if (!v) throw new Error(`missing compiled schema for ${field}`);
if (!v(middleware[field])) throw new Error(`${field}: ${ajv.errorsText(v.errors)}`);
} Type guard
function hasMiddlewareFields(mw) {
return typeof mw === "object" && mw !== null &&
["capabilities", "request", "plan", "page"].every(k => k in mw);
} Try / catch
try {
await runValidationScript();
} catch (err) {
const m = err.message.match(/^middleware (\w+): (.+)$/);
if (m) {
console.error(`Fixture field '${m[1]}' failed schema: ${m[2]}`);
process.exit(1);
}
throw err;
} Prevention
- Regenerate middleware.fixtures.json from the service rather than editing by hand.
- When changing a middleware schema's $id or shape, update the fixture and the getSchema lookup URL in validate-schemas.mjs in the same commit.
- Run the contracts validation script locally before pushing so AJV errors surface early with field-level detail.
- Keep schemas strict (additionalProperties: false) so drift fails fast with a precise path.
When it happens
Trigger: Running the contracts validation script when: middleware.fixtures.json is missing one of the four fields or misspells it (e.g. `resquest`); a fixture value violates its schema (wrong type, unknown enum, additionalProperties not allowed, missing required key); a middleware-*.schema.json file was renamed, its $id changed, or failed to compile so ajv.getSchema returns undefined; the fixture file itself is missing (readFile throws first) or malformed (JSON.parse throws first).
Common situations: Editing middleware.fixtures.json by hand for a new capability and adding a field the schema forbids; a schema $id rename in packages/shared/contracts/schemas that breaks the getSchema URL lookup; regenerating the fixture from a service whose output evolved past the schema; a merge that took the new fixture with the old schemas (or vice versa).
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- agent conformance fixtures must cover claude and pi
- adapter-specific build_sha256 values must differ
- agent conformance mismatch
- canonical span
- ${fixtureFiles[index]}…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/964ae61779d1a7a9.
Report an issue: GitHub.
Appendix: source
Thrown at packages/shared/contracts/scripts/validate-schemas.mjs:88
"recovery_handles",
"accounting_method",
"failure_fallback",
]) {
if (JSON.stringify(claude[key]) !== JSON.stringify(pi[key])) {
throw new Error(`agent conformance mismatch: ${key}`);
}
}
if (claude.build_sha256 === pi.build_sha256) {
throw new Error("adapter-specific build_sha256 values must differ");
}
if (claude.failure_fallback !== "original") {
throw new Error("unknown adapter failure must preserve original bytes");
}
const middleware = JSON.parse(await readFile(path.join(packageRoot, "..", "..", "sdk", "parity", "middleware.fixtures.json"), "utf8"));
for (const [field, schemaName] of Object.entries({ capabilities: "capabilities", request: "optimize", plan: "plan", page: "page" })) {
const validate = ajv.getSchema(`https://caveman.so/schemas/middleware-${schemaName}.schema.json`);
if (!validate?.(middleware[field])) throw new Error(`middleware ${field}: ${ajv.errorsText(validate?.errors)}`);
}
console.log(
`validated ${files.length} JSON schemas and ${fixtureFiles.length} static agent contract fixtures (not executable parity)`,
);
View on GitHub (pinned to 3ee70a1026)