paperclipai/paperclip · error · RouteError

invalid_provider

invalid_provider

Error message

Provider must be codex, opencode, claude_managed, aws_agentcore, or acpx.

What it means

harnessConfiguration validates the `provider` field of a capability issue-thread request. It must be one of the five supported harness providers — codex (default), opencode, claude_managed, aws_agentcore, or acpx — after trimming. Any other value produces this HTTP 400 RouteError with code invalid_provider.

Source

Thrown at packages/paperclip-runner/scripts/capability-issue-thread-server.mjs:212

        startedAt: null,
        completedAt: null,
      },
    ],
  });
}

class RouteError extends Error {
  constructor(status, code, message) {
    super(message);
    this.status = status;
    this.code = code;
  }
}

function harnessConfiguration(source, fallbackModel) {
  const provider = source.provider === undefined ? "codex" : String(source.provider).trim();
  if (provider !== "codex" && provider !== "opencode" && provider !== "claude_managed" && provider !== "aws_agentcore" && provider !== "acpx") {
    throw new RouteError(400, "invalid_provider", "Provider must be codex, opencode, claude_managed, aws_agentcore, or acpx.");
  }
  const rawModel = source.model === undefined ? fallbackModel : source.model;
  const model = rawModel === undefined || rawModel === null ? "" : String(rawModel).trim();
  if (model.length > 256) throw new RouteError(400, "invalid_model", "Model is too long.");
  if (provider === "opencode" && (!model || !model.includes("/"))) {
    throw new RouteError(400, "invalid_model", "OpenCode requires a provider/model value.");
  }
  if (provider === "claude_managed" && model !== "claude-sonnet-5") {
    throw new RouteError(400, "invalid_model", "Claude Managed requires exact model claude-sonnet-5.");
  }
  if (provider === "aws_agentcore" && model !== "global.anthropic.claude-sonnet-4-6") {
    throw new RouteError(400, "invalid_model", "AWS AgentCore requires exact model global.anthropic.claude-sonnet-4-6.");
  }
  const acpxAgent = source.acpxAgent === undefined ? "codex" : String(source.acpxAgent).trim();
  if (provider === "acpx") {
    if (!(acpxAgent in ACPX_QUALIFIED_MODELS)) {
      throw new RouteError(400, "invalid_acpx_agent", "ACPX agent must be claude or codex.");
    }

View on GitHub (pinned to 5716fe907e)

Solutions

  1. Set provider to exactly one of: codex, opencode, claude_managed, aws_agentcore, acpx (lowercase).
  2. Omit provider entirely to use the default "codex".
  3. Trim whitespace and check casing in the client before sending.
  4. Update the client/SDK if it still emits a provider name from an older API revision.

Example fix

// before
{ "provider": "Claude-Managed", "model": "claude-sonnet-4-5" }
// after
{ "provider": "claude_managed", "model": "claude-sonnet-4-5" }
Defensive patterns

Strategy: validation

Validate before calling

const PROVIDERS = new Set(["codex", "opencode", "claude_managed", "aws_agentcore", "acpx"]);
function assertValidProvider(p) {
  const v = p === undefined ? "codex" : String(p).trim();
  if (!PROVIDERS.has(v)) throw new Error(`provider must be one of ${[...PROVIDERS].join(", ")}`);
  return v;
}
assertValidProvider(requestBody.provider);

Type guard

function isHarnessProvider(p) {
  return p === undefined || ["codex", "opencode", "claude_managed", "aws_agentcore", "acpx"].includes(p);
}

Try / catch

try {
  const res = await fetch(url, { method: "POST", body: JSON.stringify(payload) });
  if (res.status === 400) {
    const body = await res.json();
    if (body.code === "invalid_provider") {
      // correct the provider client-side and retry once
      payload.provider = "codex";
      return fetch(url, { method: "POST", body: JSON.stringify(payload) });
    }
  }
} catch (e) { /* network errors only */ }

Prevention

When it happens

Trigger: POSTing to the capability issue-thread server with provider set to an unsupported string (e.g. "claude", "cursor", "Codex" with different case/whitespace is trimmed so case matters), a number, or a misspelled provider name.

Common situations: Typo like "claude_managed " with odd casing or "opencode-remote"; older clients sending provider names from a previous API revision; hand-written curl/test payloads using the display name instead of the slug; providers removed/renamed across versions.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@5716fe907e (2026-09-02). Data as JSON: /api/errors/94d51fe15adfade8. Report an issue: GitHub.