{"record":{"id":"47a69e9c5d5a86ec","repo":"paperclipai/paperclip","slug":"agent-name-cannot-be-empty","errorCode":null,"errorMessage":"--agent-name cannot be empty.","messagePattern":"--agent-name cannot be empty\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/test-drive.ts","lineNumber":240,"sourceCode":"\nexport function resolveTestDriveBootstrap(\n  options: TestDriveOptions,\n  env: NodeJS.ProcessEnv = process.env,\n): ResolvedTestDriveBootstrap {\n  if (options.apiKey !== undefined && options.apiKeyEnv !== undefined) {\n    throw new Error(\"--api-key and --api-key-env are mutually exclusive.\");\n  }\n\n  const harness = options.harness ?? \"claude\";\n  const definition = HARNESS_DEFINITIONS[harness];\n  if (!definition) {\n    throw new Error(`Unsupported test-drive harness: ${String(harness)}.`);\n  }\n\n  const companyName = (options.companyName ?? \"Test Company\").trim();\n  const agentName = (options.agentName ?? \"CEO\").trim();\n  if (!companyName) throw new Error(\"--company-name cannot be empty.\");\n  if (!agentName) throw new Error(\"--agent-name cannot be empty.\");\n\n  const model = options.model;\n  if (model !== undefined && (!model || model.trim() !== model)) {\n    throw new Error(\"--model cannot be empty or have surrounding whitespace.\");\n  }\n  if (\n    harness === \"opencode\" &&\n    (!model || !/^openrouter\\/[^/\\s]+(?:\\/[^/\\s]+)*$/.test(model))\n  ) {\n    throw new Error(\n      \"OpenCode test drives require --model openrouter/<model>, with no empty path segments.\",\n    );\n  }\n\n  const sourceEnvName = options.apiKeyEnv?.trim() || definition.credentialTarget;\n  if (options.apiKeyEnv !== undefined && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(sourceEnvName)) {\n    throw new Error(\"--api-key-env must name a valid environment variable.\");\n  }","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/cli/src/commands/test-drive.ts#L222-L258","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set `turnStartTimeoutMs` to a positive integer in milliseconds (e.g. 30_000) or omit it to use the 30s default.","Sanitize any env/CLI-derived value with `Number.isSafeInteger(v) && v > 0` before assigning it to options.","Remove units or stray characters from the configured value (`\"30000\"` → `30000`)."],"exampleFix":"// before\nnew RunnerdCodexTransport({ turnStartTimeoutMs: \"30s\" });\n// after\nconst v = Number(process.env.TURN_START_TIMEOUT_MS);\nnew RunnerdCodexTransport({\n  turnStartTimeoutMs: Number.isSafeInteger(v) && v > 0 ? v : 30_000,\n});","handlingStrategy":"validation","validationCode":"const v = options.turnStartTimeoutMs ?? 30_000;\nif (!Number.isSafeInteger(v) || v <= 0) {\n  throw new Error(`turnStartTimeoutMs must be a positive safe integer, got ${String(v)}`);\n}","typeGuard":"function isValidTimeoutMs(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isSafeInteger(v) && v > 0;\n}","tryCatchPattern":"try {\n  await transport.startTurn(input);\n} catch (e) {\n  if (e.message.startsWith(\"turnStartTimeoutMs must be\")) {\n    transport.reconfigure({ ...options, turnStartTimeoutMs: 30_000 }); // safe default\n  }\n}","preventionTips":["Parse numeric env/CLI config with explicit sanitization (strip units, use Number, validate).","Centralize timeout parsing in one utility that enforces positive-safe-integer.","Write unit tests for config parsing covering 0, negative, float, NaN, and string inputs."],"tags":["configuration","timeout","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}