paperclipai/paperclip · error · Error

OpenCode requires `adapterConfig.model` in provider/model fo

Error message

OpenCode requires `adapterConfig.model` in provider/model format.

What it means

Thrown by requireOpenCodeModelId (models.ts) when adapterConfig.model is missing or fails isValidOpenCodeModelId. OpenCode addresses models as provider/model (e.g. 'anthropic/claude-3-5-sonnet'), and the validator enforces that shape before any discovery runs, so an empty or slash-less value is rejected up front.

Source

Thrown at packages/adapters/opencode-local/src/server/models.ts:30

const MODELS_DISCOVERY_TIMEOUT_MS = 20_000;

function resolveOpenCodeCommand(input: unknown): string {
  const envOverride =
    typeof process.env.PAPERCLIP_OPENCODE_COMMAND === "string" &&
    process.env.PAPERCLIP_OPENCODE_COMMAND.trim().length > 0
      ? process.env.PAPERCLIP_OPENCODE_COMMAND.trim()
      : "opencode";
  return asString(input, envOverride);
}

const discoveryCache = new Map<string, { expiresAt: number; models: AdapterModel[] }>();
const VOLATILE_ENV_KEY_PREFIXES = ["PAPERCLIP_", "npm_", "NPM_"] as const;
const VOLATILE_ENV_KEY_EXACT = new Set(["PWD", "OLDPWD", "SHLVL", "_", "TERM_SESSION_ID", "HOME"]);

export function requireOpenCodeModelId(input: unknown): string {
  const model = asString(input, "").trim();
  if (!isValidOpenCodeModelId(model)) {
    throw new Error("OpenCode requires `adapterConfig.model` in provider/model format.");
  }
  return model;
}

function dedupeModels(models: AdapterModel[]): AdapterModel[] {
  const seen = new Set<string>();
  const deduped: AdapterModel[] = [];
  for (const model of models) {
    const id = model.id.trim();
    if (!id || seen.has(id)) continue;
    seen.add(id);
    deduped.push({ id, label: model.label.trim() || id });
  }
  return deduped;
}

function sortModels(models: AdapterModel[]): AdapterModel[] {
  return [...models].sort((a, b) =>

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Set adapterConfig.model to a provider/model string, e.g. 'openai/gpt-4o' or 'anthropic/claude-3-5-sonnet'.
  2. Confirm the provider segment matches a provider opencode knows (run `opencode models` to see valid prefixes).
  3. If the model id is generated dynamically, validate it with isValidOpenCodeModelId before assigning.

Example fix

// before
adapterConfig = { model: "gpt-4o" }
// after
adapterConfig = { model: "openai/gpt-4o" }
Defensive patterns

Strategy: type-guard

Validate before calling

const model = asString(adapterConfig.model, "").trim();
if (!isValidOpenCodeModelId(model)) {
  throw new Error("adapterConfig.model must be set in provider/model format before starting the run.");
}

Type guard

function isOpenCodeModelId(value: unknown): value is string {
  return typeof value === "string" && isValidOpenCodeModelId(value.trim());
}

Prevention

When it happens

Trigger: requireOpenCodeModelId(input.model) is called with input.model undefined, empty after trim, or not matching the provider/model regex.

Common situations: adapterConfig.model was never set on the agent; the model was set as a bare id ('gpt-4o') without the provider prefix; a config migration dropped the field.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/c8ee3926cfbe30b2. Report an issue: GitHub.