JuliusBrussee/caveman · error · Error

cave_harness_model_identity_missing

cave_harness_model_identity_missing

Error message

cave_harness_model_identity_missing

What it means

After a harness call finishes, the response must report which model produced the output, and that reported model must be a non-empty string. `normalizedResponseModel` reads the model identity from the upstream response (optionally stripping a `provider/` prefix) so the adapter can verify the response model matches the plan; a missing or empty value means the evidence chain for model identity is incomplete, so the adapter fails closed. This is an upstream-response contract violation, not a caller configuration error.

Source

Thrown at packages/agent/src/adapters.ts:508

  }
  return {
    provider: runtime.modelId.slice(0, separator),
    model: runtime.modelId.slice(separator + 1),
    upstreamVersion: runtime.eveVersion,
  };
}

function expectedProviderModel(plan: CavePlan): { provider: string; model: string } {
  const separator = plan.model.indexOf("/");
  if (separator < 1 || separator === plan.model.length - 1) {
    throw new Error("cave_harness_model_invalid");
  }
  return { provider: plan.model.slice(0, separator), model: plan.model.slice(separator + 1) };
}

function normalizedResponseModel(value: unknown, provider: string): string {
  if (typeof value !== "string" || value.length === 0) {
    throw new Error("cave_harness_model_identity_missing");
  }
  return value.startsWith(`${provider}/`) ? value.slice(provider.length + 1) : value;
}

function terminalFinishReason(value: unknown): boolean {
  return typeof value === "string" && ["stop", "length", "content-filter", "other"].includes(value);
}

function record(value: unknown, error: string): Record<string, unknown> {
  if (!isRecord(value)) throw new Error(error);
  return value;
}

function strictInteger(value: unknown, error: string): number {
  if (!Number.isSafeInteger(value) || Number(value) < 0) throw new Error(error);
  return Number(value);
}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. If you stub or record harness responses, include a non-empty `model` string such as `"anthropic/claude-sonnet-4-5"`.
  2. Remove any middleware or proxy that strips fields from the upstream response body.
  3. If the error appears after upgrading the pinned harness package, reinstall the exact pinned version (e.g. Vercel AI SDK 7.0.43).

Example fix

// before (test stub)
const response = { text: "done", usage: { /* ... */ } };

// after (test stub)
const response = { model: "anthropic/claude-sonnet-4-5", text: "done", usage: { /* ... */ } };
Defensive patterns

Strategy: validation

Validate before calling

function hasResponseModel(response: unknown): boolean {
  return typeof (response as Record<string, unknown> | null | undefined)?.model === "string" &&
    ((response as Record<string, unknown>).model as string).length > 0;
}

Type guard

function hasModelField<T extends object>(v: T): v is T & { model: string } {
  return typeof (v as Record<string, unknown>).model === "string" &&
    ((v as Record<string, unknown>).model as string).length > 0;
}

Try / catch

try {
  await adapter.run(request);
} catch (err) {
  if (err instanceof Error && err.message === "cave_harness_model_identity_missing") {
    // upstream response lacked model identity: fix the transport/stub, do not retry blindly
  }
}

Prevention

When it happens

Trigger: The upstream harness (Vercel AI SDK / Eve / Mastra) returns a response object whose model field is `undefined`, `null`, `""`, or a non-string — e.g. a mock transport in tests, a response-shaping middleware that strips fields, or an upstream API change that renames the field.

Common situations: Unit tests stubbing harness responses with `{ text: "..." }` and forgetting `model`; an HTTP proxy or serializer dropping the model field; upgrading the pinned harness SDK after an API rename without regenerating the adapter evidence; using a custom fetch transport that fabricates responses.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/d803ddd4e1d634a6. Report an issue: GitHub.