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

  1. Read the error text: the field name tells you which fixture section failed, and errorsText lists the exact AJV violations (path, keyword, expected value).
  2. Fix the offending value in sdk/parity/middleware.fixtures.json to satisfy packages/shared/contracts/schemas/middleware-<name>.schema.json.
  3. 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.
  4. If the fixture legitimately models new behavior, update the schema first (bump version if it's a breaking wire change), then regenerate the fixture.
  5. 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

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


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)