paperclipai/paperclip · error · Error

--agent-name cannot be empty.

Error message

--agent-name cannot be empty.

What it means

The `#startTurn` handler validates the configured `turnStartTimeoutMs` option: it must be a positive safe integer (it defaults to 30_000). Passing a non-integer, zero, negative number, or a value beyond Number.MAX_SAFE_INTEGER causes this synchronous validation error before any command deadline is computed.

Source

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

export function resolveTestDriveBootstrap(
  options: TestDriveOptions,
  env: NodeJS.ProcessEnv = process.env,
): 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.");
  }

View on GitHub (pinned to 01ad858492)

Solutions

  1. Set `turnStartTimeoutMs` to a positive integer in milliseconds (e.g. 30_000) or omit it to use the 30s default.
  2. Sanitize any env/CLI-derived value with `Number.isSafeInteger(v) && v > 0` before assigning it to options.
  3. Remove units or stray characters from the configured value (`"30000"` → `30000`).

Example fix

// before
new RunnerdCodexTransport({ turnStartTimeoutMs: "30s" });
// after
const v = Number(process.env.TURN_START_TIMEOUT_MS);
new RunnerdCodexTransport({
  turnStartTimeoutMs: Number.isSafeInteger(v) && v > 0 ? v : 30_000,
});
Defensive patterns

Strategy: validation

Validate before calling

const v = options.turnStartTimeoutMs ?? 30_000;
if (!Number.isSafeInteger(v) || v <= 0) {
  throw new Error(`turnStartTimeoutMs must be a positive safe integer, got ${String(v)}`);
}

Type guard

function isValidTimeoutMs(v: unknown): v is number {
  return typeof v === "number" && Number.isSafeInteger(v) && v > 0;
}

Try / catch

try {
  await transport.startTurn(input);
} catch (e) {
  if (e.message.startsWith("turnStartTimeoutMs must be")) {
    transport.reconfigure({ ...options, turnStartTimeoutMs: 30_000 }); // safe default
  }
}

Prevention

When it happens

Trigger: Setting `turnStartTimeoutMs` to 0, a negative value, a float (e.g. 2.5), NaN, Infinity, or a non-number (which survives the `??` default only if it's not null/undefined) in the transport options.

Common situations: Parsing the timeout from an env var or CLI flag without sanitizing (`Number("30s")` → NaN); computing the value via arithmetic producing a float; copying a config where the field was renamed and an old string value leaks through.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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