{"record":{"id":"16b3a81fe6dadae8","repo":"paperclipai/paperclip","slug":"timeoutms-must-be-an-integer-between-1-and-86400000","errorCode":null,"errorMessage":"timeoutMs must be an integer between 1 and 86400000.","messagePattern":"timeoutMs must be an integer between 1 and 86400000\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/createos/src/config.ts","lineNumber":36,"sourceCode":"    return value.trim();\n  };\n  const apiUrl = text(\"apiUrl\");\n  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.\");","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/createos/src/config.ts#L18-L54","documentation":"parseConfig validates the optional timeoutMs as an integer between 1 and 86,400,000 (1 ms to 24 hours). Non-integer numbers, zero, negative values, and values above 24h are rejected. If omitted, a default of 300,000 ms (5 minutes) applies.","triggerScenarios":"Passing timeoutMs as a non-integer (e.g. 1.5), a string (\"5000\"), 0, a negative number, or greater than 86400000 in the CreateOS environment config, then calling parseConfig via client/config construction or the validate/probe hooks.","commonSituations":"Hand-editing JSON and quoting the number; entering hours-as-seconds (e.g. 172800000 for '48 hours'); pasting a duration like '30m' as a raw value; typos adding extra digits.","solutions":["Set timeoutMs to an integer number of milliseconds between 1 and 86400000, e.g. 600000 for 10 minutes.","Remove the key entirely to use the 5-minute default.","Convert duration strings/units to milliseconds before writing the config.","Clamp large values to 86400000 if a longer effective timeout is genuinely needed (split work into multiple executions)."],"exampleFix":"// before\n{ \"timeoutMs\": \"30m\" }\n// after\n{ \"timeoutMs\": 1800000 }","handlingStrategy":"validation","validationCode":"const t = cfg.timeoutMs ?? 300_000;\nif (!Number.isInteger(t) || t < 1 || t > 86_400_000) throw new Error('timeoutMs must be an integer 1..86400000 ms');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write timeoutMs as a raw integer of milliseconds, never a quoted string","Remember the 24h ceiling and the 5-minute default","Convert minutes/seconds to milliseconds at config-authoring time"],"tags":["config","validation","timeout","range-check"],"backgroundTag":"value-out-of-range","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"}