{"record":{"id":"492c3dc3cff29f21","repo":"paperclipai/paperclip","slug":"reuselease-must-be-a-boolean","errorCode":null,"errorMessage":"reuseLease must be a boolean.","messagePattern":"reuseLease must be a boolean\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/createos/src/config.ts","lineNumber":39,"sourceCode":"  if (!apiUrl) throw new Error(\"CreateOS requires an API URL.\");\n  let url: URL;\n  try { url = new URL(apiUrl); } catch { throw new Error(\"CreateOS API URL is invalid.\"); }\n  // Configuration is board-owned, but never follow redirects with the API key.\n  // Plain HTTP is useful for a loopback development server only.\n  const loopback = [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname);\n  if ((url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback)) ||\n      url.username || url.password || url.search || url.hash ||\n      ![\"\", \"/\", \"/v1\", \"/v1/\"].includes(url.pathname)) {\n    throw new Error(\"CreateOS API URL must be an HTTPS origin (optionally ending in /v1); HTTP is allowed on loopback only.\");\n  }\n  const shape = text(\"shape\");\n  if (!shape) throw new Error(\"CreateOS requires a shape from its shape catalog.\");\n  const timeoutMs = raw.timeoutMs ?? 300_000;\n  if (typeof timeoutMs !== \"number\" || !Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 86_400_000) {\n    throw new Error(\"timeoutMs must be an integer between 1 and 86400000.\");\n  }\n  if (raw.reuseLease != null && typeof raw.reuseLease !== \"boolean\") {\n    throw new Error(\"reuseLease must be a boolean.\");\n  }\n  return {\n    apiUrl: url.origin,\n    apiKey: text(\"apiKey\"),\n    shape,\n    rootfs: text(\"rootfs\"),\n    region: text(\"region\"),\n    timeoutMs,\n    reuseLease: raw.reuseLease === true,\n  };\n}\n\nexport function resolveApiKey(config: CreateosConfig): string {\n  if (!config.apiKey && config.apiUrl !== \"https://api.sb.createos.sh\") {\n    throw new Error(\"Custom CreateOS API endpoints require an explicit environment API key; the host fallback is only available for https://api.sb.createos.sh.\");\n  }\n  const key = config.apiKey ?? process.env.CREATEOS_API_KEY?.trim();\n  if (!key || /[\\r\\n\\0]/.test(key)) {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/createos/src/config.ts#L21-L57","documentation":"parseConfig validates the optional reuseLease option: if present it must be a boolean. The plugin converts it to a strict true/false (raw.reuseLease === true), so truthy non-boolean values like \"true\" or 1 are rejected rather than coerced.","triggerScenarios":"Setting reuseLease to a string (\"true\"/\"false\"), a number (0/1), null-as-string, or an object in the CreateOS environment config and calling parseConfig via client/config construction or the validate/probe hooks.","commonSituations":"Editing a JSON/YAML config by hand and leaving the value quoted; environment-variable-driven configs where everything arrives as a string; copying a JS config where the value was a 0/1 flag.","solutions":["Change reuseLease to a real boolean: true or false (unquoted).","Remove the key entirely when the default (false) is acceptable — only non-null non-booleans are rejected.","If the config comes from env vars, parse it first, e.g. reuseLease: process.env.REUSE_LEASE === 'true'."],"exampleFix":"// before\n{ \"reuseLease\": \"true\" }\n// after\n{ \"reuseLease\": true }","handlingStrategy":"validation","validationCode":"if (cfg.reuseLease != null && typeof cfg.reuseLease !== 'boolean') throw new Error('reuseLease must be a boolean');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use real JSON booleans, not \"true\"/\"false\" strings","Parse string env-driven flags with === 'true'","Omit the key entirely to accept the default"],"tags":["config","validation","type-mismatch","boolean"],"backgroundTag":"config-type-mismatch","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}