paperclipai/paperclip · error

OpenCode proxy requires model in provider/model form

Error message

OpenCode proxy requires model in provider/model form

What it means

The OpenCode proxy requires the model parameter to name both provider and model in 'provider/model' form; it uses the slash as the delimiter to configure the active model, so a bare model name is rejected.

Source

Thrown at packages/paperclip-runner/src/cli/opencode-app-server-proxy.ts:96

function runtimeDirectory(): string {
  const configured = process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR?.trim();
  if (!configured)
    throw new Error("PAPERCLIP_OPENCODE_RUNTIME_DIR is required");
  return resolve(configured);
}

async function open(
  params: Record<string, unknown>,
  resume: boolean,
): Promise<Record<string, unknown>> {
  if (session)
    return threadResponse(
      session.ids().providerSessionId ?? session.ids().driverSessionId,
    );
  cwd = resolve(text(params.cwd, process.cwd()));
  const model = text(params.model);
  if (!model.includes("/"))
    throw new Error("OpenCode proxy requires model in provider/model form");
  activeModel = model;
  const dynamicTools = Array.isArray(params.dynamicTools)
    ? params.dynamicTools.map(record)
    : [];
  const runtimeContextPath =
    process.env.PAPERCLIP_NATIVE_RUNTIME_CONTEXT_PATH?.trim();
  const runtimeContext = runtimeContextPath
    ? parseNativeRuntimeContext(
        JSON.parse(readFileSync(runtimeContextPath, "utf8")),
      )
    : null;
  driver = new OpenCodeServerDriver({
    model,
    permissionMode: parseOpenCodeProxyPermissionMode(
      process.env.PAPERCLIP_OPENCODE_PERMISSION_MODE,
    ),
    command: launchBinding.command,
    commandFd: launchBinding.commandFd,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Pass the fully qualified model, e.g. 'anthropic/claude-sonnet-4' or 'openai/gpt-5'
  2. Prefix the bare model slug with the correct provider id before calling open
  3. Validate the model string in the caller/UI before dispatching

Example fix

// before
openSession({ cwd, model: 'claude-sonnet-4' });
// after
openSession({ cwd, model: 'anthropic/claude-sonnet-4' });
Defensive patterns

Strategy: validation

Validate before calling

const model = String(params.model ?? '');
if (!model.includes('/')) throw new Error('model must be provider/model, e.g. anthropic/claude-sonnet-4');

Type guard

function isQualifiedModel(m: unknown): m is string { return typeof m === 'string' && m.includes('/'); }

Try / catch

try { await proxy.open(params, resume); }
catch (e) { if (String(e.message).includes('provider/model form')) { params.model = qualifyModel(params.model); await proxy.open(params, resume); } else throw e; }

Prevention

When it happens

Trigger: Calling open() with params.model set to a string without a '/' (e.g. 'claude-sonnet-4', ''), when resuming is not in effect (cwd path taken).

Common situations: Passing just the model id from a UI dropdown that omits the provider prefix; copying model names from provider docs that show only the slug; empty model param because the field wasn't filled.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/0e24999848556193. Report an issue: GitHub.