paperclipai/paperclip · critical · Error

--model cannot be empty or have surrounding whitespace.

Error message

--model cannot be empty or have surrounding whitespace.

What it means

While starting a provider turn, the transport polls for the provider turn-start signal, pumping events and checking failures each 10ms iteration until the deadline. If the runnerd process exits before the provider turn is observed as started, it throws this error — the turn cannot proceed on a dead runner.

Source

Thrown at cli/src/commands/test-drive.ts:244

): ResolvedTestDriveBootstrap {
  if (options.apiKey !== undefined && options.apiKeyEnv !== undefined) {
    throw new Error("--api-key and --api-key-env are mutually exclusive.");
  }

  const harness = options.harness ?? "claude";
  const definition = HARNESS_DEFINITIONS[harness];
  if (!definition) {
    throw new Error(`Unsupported test-drive harness: ${String(harness)}.`);
  }

  const companyName = (options.companyName ?? "Test Company").trim();
  const agentName = (options.agentName ?? "CEO").trim();
  if (!companyName) throw new Error("--company-name cannot be empty.");
  if (!agentName) throw new Error("--agent-name cannot be empty.");

  const model = options.model;
  if (model !== undefined && (!model || model.trim() !== model)) {
    throw new Error("--model cannot be empty or have surrounding whitespace.");
  }
  if (
    harness === "opencode" &&
    (!model || !/^openrouter\/[^/\s]+(?:\/[^/\s]+)*$/.test(model))
  ) {
    throw new Error(
      "OpenCode test drives require --model openrouter/<model>, with no empty path segments.",
    );
  }

  const sourceEnvName = options.apiKeyEnv?.trim() || definition.credentialTarget;
  if (options.apiKeyEnv !== undefined && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(sourceEnvName)) {
    throw new Error("--api-key-env must name a valid environment variable.");
  }
  const credential = options.apiKey ?? env[sourceEnvName];
  if (!credential || credential.trim().length === 0) {
    throw new Error(
      `No credential found. Set ${sourceEnvName}, pass --api-key-env <variable>, or pass --api-key <value>.`,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check runnerd stdout/stderr and exit code to find why it exited at startup, and fix the spawn configuration or binary.
  2. Verify the runnerd binary path/version is installed and executable in the environment.
  3. Add health/startup validation before issuing a turn so a broken runner is detected earlier, then retry once healthy.

Example fix

// before
const transport = new RunnerdCodexTransport({ runnerdPath: "/opt/runnerd" }); // missing binary
// after
if (!existsSync(runnerdPath)) await installRunnerd(runnerdPath);
const transport = new RunnerdCodexTransport({ runnerdPath });
Defensive patterns

Strategy: try-catch

Validate before calling

if (!existsSync(runnerdPath) || !(await isExecutable(runnerdPath))) {
  throw new Error(`runnerd binary not ready at ${runnerdPath}`);
}

Type guard

null

Try / catch

try {
  await transport.startTurn(input);
} catch (e) {
  if (e.message === "runnerd exited before provider turn startup") {
    const { code, stderr } = await transport.getLastExitInfo();
    log.error("runnerd exited", { code, stderr });
    await restartRunnerd(root);
    await transport.startTurn(input); // one retry after restart
  }
}

Prevention

When it happens

Trigger: During `#startTurn`'s wait loop, `#runnerHasExited()` returns true before `providerTurnStarted()` becomes true (runnerd crashed/exited early, e.g. bad spawn args, immediate panic, port conflict).

Common situations: Runnerd binary missing or crashing on startup; invalid model/config causing immediate exit; resource exhaustion (OOM) at turn start; environment differences after an upgrade where runnerd no longer boots.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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