{"record":{"id":"5e8857de8d0cbe00","repo":"paperclipai/paperclip","slug":"invalid-createos-command-timeout","errorCode":null,"errorMessage":"Invalid CreateOS command timeout.","messagePattern":"Invalid CreateOS command timeout\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/createos/src/plugin.ts","lineNumber":85,"sourceCode":"  }\n\n  async function stopActive(scope: string) {\n    const calls = [...(active.get(scope) ?? [])];\n    for (const call of calls) call.controller.abort();\n    await Promise.all(calls.map((call) => call.done));\n  }\n\n  async function track<T>(\n    params: PluginEnvironmentDriverBaseParams & { lease: PluginEnvironmentLease },\n    work: (client: CreateosClient, signal: AbortSignal) => Promise<T>,\n    timeoutOverride?: number,\n  ): Promise<T> {\n    if (!params.lease.providerLeaseId || !metadataMatches(params, params.lease.metadata)) throw new Error(\"CreateOS execution requires a lease from this environment.\");\n    const scope = key(params, params.lease.providerLeaseId);\n    if (shuttingDown || closing.has(scope) || unconfirmedCleanup.has(scope)) throw new Error(\"CreateOS lease is closing or requires cleanup.\");\n    const config = parseConfig(params.config);\n    const timeoutMs = timeoutOverride ?? config.timeoutMs;\n    if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 86_400_000) throw new Error(\"Invalid CreateOS command timeout.\");\n    const controller = new AbortController();\n    let finish!: () => void;\n    const entry: Active = { controller, done: new Promise<void>((resolve) => { finish = resolve; }) };\n    const calls = active.get(scope) ?? new Set<Active>();\n    calls.add(entry);\n    active.set(scope, calls);\n    try {\n      return await work(new CreateosClient(config), AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]));\n    } catch (error) {\n      if (error instanceof CreateosCleanupError) unconfirmedCleanup.add(scope);\n      throw error;\n    } finally {\n      calls.delete(entry);\n      if (calls.size === 0) active.delete(scope);\n      finish();\n    }\n  }\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/createos/src/plugin.ts#L67-L103","documentation":"track() validates the effective command timeout: it must be a positive integer within 1 ms..86,400,000 ms (24h). The value comes from the explicit timeoutOverride (e.g. params.timeoutMs from onEnvironmentExecute) or falls back to the config's timeoutMs. This error is thrown when the resolved value is not an integer, is less than 1, or exceeds 24 hours.","triggerScenarios":"onEnvironmentExecute is called with a non-integer timeoutMs (NaN, undefined when no config default exists, a float), a zero or negative timeout, or a timeout above 86,400,000; or the CreateOS config's timeoutMs itself is out of range and no override is supplied.","commonSituations":"Passing a duration in seconds (e.g. 300) instead of milliseconds; computing timeout from a Date diff that yields NaN; serializing timeouts through JSON where they become strings; configuring timeoutMs: 0 intending 'no timeout' when 0 is invalid; typo'd config like timeout: 60000 that leaves timeoutMs undefined.","solutions":["Pass an integer millisecond value between 1 and 86,400,000 as the operation's timeoutMs (or timeoutOverride).","Check the CreateOS environment config: timeoutMs must be a valid integer ms value — run onEnvironmentValidateConfig to catch it early.","Convert second-based durations to milliseconds (seconds * 1000) before passing them.","Guard computed timeouts: reject NaN/undefined with a default instead of forwarding them to the driver."],"exampleFix":"// before: seconds value forwarded as if milliseconds\nawait driver.execute({ ...params, timeoutMs: 300 });\n// after: normalize and validate before calling\nconst timeoutMs = Math.floor(Number(process.env.CMD_TIMEOUT_S ?? 600) * 1000);\nif (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 86_400_000) {\n  throw new RangeError(`timeoutMs must be an integer in [1, 86400000], got ${timeoutMs}`);\n}\nawait driver.execute({ ...params, timeoutMs });","handlingStrategy":"validation","validationCode":"function assertValidTimeoutMs(ms) {\n  const n = Number(ms);\n  if (!Number.isInteger(n) || n < 1 || n > 86_400_000) {\n    throw new RangeError(`timeoutMs must be an integer in [1, 86400000], got ${ms}`);\n  }\n  return n;\n}\nconst timeoutMs = assertValidTimeoutMs(params.timeoutMs ?? config.timeoutMs);","typeGuard":"function isValidTimeoutMs(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isInteger(v) && v >= 1 && v <= 86_400_000;\n}","tryCatchPattern":"try {\n  return await driver.execute({ ...params, timeoutMs });\n} catch (e) {\n  if (e.message === \"Invalid CreateOS command timeout.\") {\n    logger.warn(`bad timeoutMs=${params.timeoutMs}; falling back to 600000ms`);\n    return await driver.execute({ ...params, timeoutMs: 600_000 });\n  }\n  throw e;\n}","preventionTips":["Always express timeouts in integer milliseconds; convert from seconds explicitly.","Run onEnvironmentValidateConfig once at setup to catch bad timeoutMs in config.","Clamp computed timeouts to [1, 86_400_000] before invoking the driver.","Never use 0 or undefined to mean 'no timeout' — pick a large-but-valid cap like 86_400_000."],"tags":["timeout","validation","configuration","argument-validation"],"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-22T01:17:13.364Z"}