{"record":{"id":"0229892c349f5cf9","repo":"earendil-works/pi","slug":"invalid-timeout-must-be-a-finite-number-of-second","errorCode":null,"errorMessage":"Invalid timeout: must be a finite number of seconds","messagePattern":"Invalid timeout: must be a finite number of seconds","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/harness/tools/bash.ts","lineNumber":44,"sourceCode":"\tenv: Record<string, string>;\n\tinheritEnv: boolean;\n}\n\nexport type BashPrepare<TContext extends ExecutionToolContext = ExecutionToolContext> = (\n\texecution: BashExecution,\n\tcontext: TContext,\n\tsignal?: AbortSignal,\n) => void | Promise<void>;\n\nexport interface BashToolOptions<TContext extends ExecutionToolContext = ExecutionToolContext> {\n\tcommandPrefix?: string;\n\tprepare?: BashPrepare<TContext>;\n}\n\nfunction validateTimeout(timeout: number | undefined): void {\n\tif (timeout === undefined) return;\n\tif (!Number.isFinite(timeout) || timeout <= 0) {\n\t\tthrow new Error(\"Invalid timeout: must be a finite number of seconds\");\n\t}\n\tif (timeout > MAX_TIMEOUT_SECONDS) {\n\t\tthrow new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);\n\t}\n}\n\nexport function createBashTool<TContext extends ExecutionToolContext = ExecutionToolContext>(\n\toptions?: BashToolOptions<TContext>,\n): AgentHarnessTool<TContext, typeof bashSchema, BashToolDetails | undefined> {\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tparameters: bashSchema,\n\t\tasync execute(_toolCallId, { command, timeout }, signal, onUpdate, context) {\n\t\t\tvalidateTimeout(timeout);\n\t\t\tconst { env } = context;\n\t\t\tconst execution: BashExecution = {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/earendil-works/pi/blob/4af9d21d3b4d664e4a29fcabfec85171077248e3/packages/agent/src/harness/tools/bash.ts#L26-L62","documentation":"The bash tool validates its optional timeout at the top of execute (bash.ts:60): it must be a finite number of seconds greater than zero, or omitted entirely (omission means no timeout at all). NaN, Infinity, 0 and negative values throw a plain Error before any command runs. The field is seconds, not milliseconds.","triggerScenarios":"Tool input { command, timeout: 0 }; timeout computed as (end - start) / 1000 where an operand is undefined and the result is NaN; -1 passed as an 'unlimited' sentinel; Infinity leaking from unconstrained division.","commonSituations":"A config default of 0 meaning 'disabled' forwarded as the timeout; millisecond/second mix-ups that collapse to zero or negative differences; model-generated tool calls emitting timeout: 0.","solutions":["Omit timeout when you want no limit instead of passing a sentinel","Clamp computed values: Number.isFinite(t) ? Math.min(Math.max(t, 1), 2147483.647) : undefined","Fix the unit: divide millisecond values by 1000 before passing"],"exampleFix":"// before\nawait bashTool.execute(id, { command: 'npm test', timeout: 0 }); // throws\n\n// after\nawait bashTool.execute(id, { command: 'npm test' }); // no timeout","handlingStrategy":"validation","validationCode":"const MAX_TIMEOUT_SECONDS = 2_147_483_647 / 1000;\nconst normalizeTimeout = (t: number | undefined): number | undefined =>\n  t === undefined || !Number.isFinite(t) || t <= 0\n    ? undefined\n    : Math.min(t, MAX_TIMEOUT_SECONDS);\n\nawait bashTool.execute(id, { command, timeout: normalizeTimeout(rawTimeout) });","typeGuard":"function isValidTimeout(t: unknown): t is number {\n  return typeof t === 'number' && Number.isFinite(t) && t > 0;\n}","tryCatchPattern":null,"preventionTips":["Treat the field as seconds; convert millisecond values with /1000","Use undefined (omit the field) for no timeout, never 0 or -1 sentinels","Clamp model- or config-supplied timeouts before invoking the tool"],"tags":["bash","timeout","argument-validation","tool-input"],"backgroundTag":"invalid-timeout-value","analyzedSha":"4af9d21d3b4d664e4a29fcabfec85171077248e3","analyzedAt":"2026-08-24T13:07:14.692Z","schemaVersion":2},"datasetVersion":"2026-08-24T17:17:21.512Z"}