{"record":{"id":"f4bcb77eefb0b37f","repo":"remotion-dev/remotion","slug":"maxretries-must-be-a-number-but-is-json-stringi","errorCode":null,"errorMessage":"maxRetries must be a number, but is ${JSON.stringify(maxRetries)}","messagePattern":"maxRetries must be a number, but is (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/cloudrun/src/shared/validate-retries.ts","lineNumber":5,"sourceCode":"export function validateMaxRetries(\n\tmaxRetries: unknown,\n): asserts maxRetries is number {\n\tif (typeof maxRetries !== 'number') {\n\t\tthrow new TypeError(\n\t\t\t'maxRetries must be a number, but is ' + JSON.stringify(maxRetries),\n\t\t);\n\t}\n\n\tif (!Number.isFinite(maxRetries)) {\n\t\tthrow new TypeError('maxRetries must be finite, but is ' + maxRetries);\n\t}\n\n\tif (Number.isNaN(maxRetries)) {\n\t\tthrow new TypeError('maxRetries is NaN');\n\t}\n\n\tif (maxRetries < 0) {\n\t\tthrow new TypeError(`maxRetries cannot be negative but is ${maxRetries}`);\n\t}\n\n\tif (maxRetries % 1 !== 0) {\n\t\tthrow new TypeError(","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/cloudrun/src/shared/validate-retries.ts#L1-L23","documentation":"Thrown by validateMaxRetries() in @remotion/cloudrun when the maxRetries option is not of type 'number'. The function is a TypeScript assertion (asserts maxRetries is number) used to guard Cloud Run render/deploy retry behavior, and this is the first check in a chain: type, finiteness, NaN, sign, then integrality. It uses JSON.stringify to safely render any non-number value in the message.","triggerScenarios":"Calling a Cloud Run render or deploy API with a maxRetries value that is a string, undefined, null, boolean, array, or object. Most commonly the value comes from process.env (always a string) or a JSON config file where the value was quoted.","commonSituations":"Reading retries from an environment variable without coercing with Number(); loading options from a parsed JSON/YAML config where maxRetries was written as \"3\" instead of 3; passing a value typed as string | number without narrowing.","solutions":["Coerce the input before passing it: Number(process.env.MAX_RETRIES), and provide a numeric default when it is unset.","If the value comes from config, ensure the source has no quotes around the number (JSON: 3, not \"3\").","Add a type guard so a non-number is rejected with your own error before reaching the Cloud Run API."],"exampleFix":"// before\nrenderMediaOnCloudRun({ ...opts, maxRetries: process.env.MAX_RETRIES });\n\n// after\nconst retries = Number(process.env.MAX_RETRIES);\nrenderMediaOnCloudRun({\n  ...opts,\n  maxRetries: Number.isFinite(retries) ? retries : 1,\n});","handlingStrategy":"validation","validationCode":"if (typeof maxRetries !== 'number') {\n  throw new TypeError(`maxRetries must be a number, got ${typeof maxRetries}`);\n}","typeGuard":"const isMaxRetries = (v: unknown): v is number =>\n  typeof v === 'number' &&\n  Number.isFinite(v) &&\n  Number.isInteger(v) &&\n  v >= 0;","tryCatchPattern":null,"preventionTips":["Never pass env vars (strings) straight into numeric options; coerce with Number() first.","Type render option objects explicitly so non-number maxRetries is a compile error.","Default optional retry counts to a numeric literal rather than leaving them undefined."],"tags":["cloudrun","validation","typescript","configuration"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}