{"record":{"id":"313c04b9ce4b8704","repo":"can1357/oh-my-pi","slug":"destination-option-key-must-be-a-finite-number","errorCode":null,"errorMessage":"Destination option ${key} must be a finite number","messagePattern":"Destination option (.+?) must be a finite number","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploader-runtime.ts","lineNumber":65,"sourceCode":"\tconst value = config.options[key];\n\tif (value === undefined) throw new Error(`Missing required destination option: ${key}`);\n\treturn value;\n}\n\n/** Read a string option, returning a fallback when it is absent. */\nexport function optionString(config: DestinationRuntimeConfig, key: string, fallback?: string): string | undefined {\n\tconst value = config.options[key];\n\tif (value === undefined) return fallback;\n\tif (typeof value !== \"string\") throw new Error(`Destination option ${key} must be a string`);\n\treturn value;\n}\n\n/** Read a number option, returning a fallback when it is absent. */\nexport function optionNumber(config: DestinationRuntimeConfig, key: string, fallback?: number): number | undefined {\n\tconst value = config.options[key];\n\tif (value === undefined) return fallback;\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) {\n\t\tthrow new Error(`Destination option ${key} must be a finite number`);\n\t}\n\treturn value;\n}\n\n/** Read a boolean option, returning a fallback when it is absent. */\nexport function optionBoolean(config: DestinationRuntimeConfig, key: string, fallback?: boolean): boolean | undefined {\n\tconst value = config.options[key];\n\tif (value === undefined) return fallback;\n\tif (typeof value !== \"boolean\") throw new Error(`Destination option ${key} must be a boolean`);\n\treturn value;\n}\n\n/** Read a credential without exposing its value in an error. */\nexport function credentialString(config: DestinationRuntimeConfig, key: string): string | undefined {\n\tconst value = config.credentials[key];\n\treturn value === \"\" ? undefined : value;\n}\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploader-runtime.ts#L47-L83","documentation":"optionNumber reads a numeric destination option and throws when the value is not a number or is NaN/Infinity. Numeric options (port, expiryDays, ttlSeconds) must be real finite numbers because they are used in arithmetic and URL construction downstream. This guard prevents string-typed numbers from leaking into numeric code paths.","triggerScenarios":"Calling optionNumber(config, key) — via port, expiryDays, or ttlSeconds — when config.options[key] is a string like \"3600\", a boolean, or a non-finite number such as Infinity produced by an expression in config.","commonSituations":"JSON config with `\"ttlSeconds\": \"3600\"` (quoted), computed values yielding Infinity, YAML unquoted floats misparsed, or users copying durations like \"1h\" into a numeric field.","solutions":["Remove quotes so the value is a JSON/YAML number: `\"ttlSeconds\": 3600`.","Convert duration strings to the numeric field the option expects, or use the string-typed `ttl` option if the destination supports one.","Check for Infinity/NaN sources if the value is generated programmatically before passing it into options."],"exampleFix":"// before\n{ \"options\": { \"port\": \"8080\" } }\n// after\n{ \"options\": { \"port\": 8080 } }","handlingStrategy":"validation","validationCode":"function assertNumberOption(options: Record<string, unknown>, key: string): void {\n  const v = options[key];\n  if (v !== undefined && (typeof v !== \"number\" || !Number.isFinite(v))) throw new Error(`option ${key} must be a finite number`);\n}\nassertNumberOption(config.options, \"ttlSeconds\");","typeGuard":"const isFiniteNumber = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v);","tryCatchPattern":"try {\n  const port = optionNumber(config, \"port\");\n} catch (err) {\n  throw new Error(`destination config: ${String(err)}`, { cause: err });\n}","preventionTips":["Never quote numbers in JSON/YAML config.","Coerce env-var strings with Number() and check Number.isFinite before building options.","Guard computed values against division by zero that yields Infinity/NaN."],"tags":["config","validation","type-error"],"backgroundTag":"invalid-config-option-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}