{"record":{"id":"182908d54f0db247","repo":"juspay/hyperswitch","slug":"cannot-coerce-value-to-number","errorCode":null,"errorMessage":"Cannot coerce \"${value}\" to number","messagePattern":"Cannot coerce \"(.+?)\" to number","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cypress-tests/cypress/e2e/configs/Payment/Utils.js","lineNumber":867,"sourceCode":"\n  // Coerce value based on expected type\n  const normalizedconnectorTransactionID = coerceValue(\n    connectorTransactionID,\n    config.type\n  );\n\n  target[finalKey] = normalizedconnectorTransactionID;\n}\n\nfunction coerceValue(value, type) {\n  switch (type) {\n    case \"string\":\n      return String(value);\n\n    case \"number\": {\n      const num = Number(value);\n      if (!Number.isFinite(num)) {\n        throw new Error(`Cannot coerce \"${value}\" to number`);\n      }\n      if (!Number.isSafeInteger(num)) {\n        return BigInt(value);\n      }\n      return num;\n    }\n\n    default:\n      return value;\n  }\n}\n\nexport function stringifyWithBigInt(obj) {\n  return JSON.stringify(obj, (_, value) =>\n    typeof value === \"bigint\" ? `__bigint__${value}` : value\n  ).replace(/\"__bigint__(\\d+)\"/g, \"$1\");\n}\n","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/juspay/hyperswitch/blob/9b8b89dc378b62c9a6feda647bad4719d2de7699/cypress-tests/cypress/e2e/configs/Payment/Utils.js#L849-L885","documentation":"Thrown by coerceValue in Payment/Utils.js when config.type is 'number' and Number(value) is not finite. The coercion supports string and number types for webhook normalization (returning BigInt when the number exceeds the safe-integer range), so any value that cannot parse as a number — 'txn_123', undefined, 'abc' — throws with the offending value quoted.","triggerScenarios":"A normalization entry { type: 'number' } receives a connector transaction id that is alphanumeric ('pay_123ABC') or undefined; Number('pay_123ABC') is NaN, so Number.isFinite fails and the error names the value.","commonSituations":"Connector ids that look numeric for one connector (Stripe 'pi_...' never is) inspire a 'number' type; the txn id field is optional and missing in some webhook variants; config copied from a connector with integer ids to one with prefixed ids.","solutions":["Change the normalization entry's type to 'string' for alphanumeric transaction ids","If the value should be numeric, fix the source of the value so it parses (e.g. use the numeric part or ensure the field exists)","Remove the type property entirely — the default branch returns the value unchanged, which is right for opaque ids"],"exampleFix":"// before\nsetNormalizedValue(webhookBody, { path: 'data.body.id', type: 'number' }, 'pay_123ABC');\n// throws: Cannot coerce \"pay_123ABC\" to number\n\n// after\nsetNormalizedValue(webhookBody, { path: 'data.body.id', type: 'string' }, 'pay_123ABC');","handlingStrategy":"type-guard","validationCode":"// Only declare type 'number' when the id really is numeric\nfunction looksNumeric(v) {\n  return v !== undefined && v !== null && Number.isFinite(Number(v));\n}\nif (config.type === 'number' && !looksNumeric(connectorTransactionID)) {\n  config = { ...config, type: 'string' }; // opaque ids stay strings\n}","typeGuard":"/** @param {unknown} v @returns {v is string | number} */\nfunction isCoercibleToNumber(v) {\n  if (v === null || v === undefined) return false;\n  return Number.isFinite(Number(v));\n}","tryCatchPattern":null,"preventionTips":["Default normalization type to string (or omit type) for connector transaction ids","Remember null coerces to 0 but undefined/NaN strings throw — validate presence too","BigInt path only engages for finite but unsafe integers, so huge numeric strings are fine"],"tags":["cypress","webhook","type-coercion","configuration"],"backgroundTag":null,"analyzedSha":"9b8b89dc378b62c9a6feda647bad4719d2de7699","analyzedAt":"2026-08-16T09:01:53.433Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}