{"record":{"id":"3e6a134ffc3ef7a6","repo":"Stirling-Tools/Stirling-PDF","slug":"invalid-real-world-distance-must-be-positive","errorCode":null,"errorMessage":"Invalid real-world distance (must be positive)","messagePattern":"Invalid real-world distance \\(must be positive\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/utils/measurementUtils.ts","lineNumber":367,"sourceCode":"    return null;\n  }\n\n  // ratio = factor / baseFactor\n  const ratio = factor / baseFactor;\n  return Number.isFinite(ratio) && ratio > 0 ? ratio : null;\n}\n\nexport function calculateCalibratedScale(\n  pdfDistancePts: number,\n  realDistance: number,\n  unit: string,\n): MeasureScale {\n  if (!Number.isFinite(pdfDistancePts) || pdfDistancePts <= 0) {\n    throw new Error(\"Invalid PDF distance (must be positive)\");\n  }\n\n  if (!Number.isFinite(realDistance) || realDistance <= 0) {\n    throw new Error(\"Invalid real-world distance (must be positive)\");\n  }\n\n  const baseFactor = getUnitFactor(unit);\n  if (!baseFactor) {\n    throw new Error(`Unsupported unit: ${unit}`);\n  }\n\n  const factor = realDistance / pdfDistancePts;\n  const ratio = deriveRatioFromFactor(factor, unit);\n\n  return {\n    factor,\n    ratio,\n    unit,\n  };\n}\n\nexport function createCalibrationMetadata(","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/utils/measurementUtils.ts#L349-L385","documentation":"Thrown by calculateCalibratedScale when realDistance fails Number.isFinite or is <= 0. realDistance is the known real-world length the user enters to calibrate the scale; it is divided by pdfDistancePts, so zero or negative values make the resulting factor meaningless.","triggerScenarios":"User submits an empty or '0' real-distance input field; a localized decimal comma ('1,5') parsed with parseFloat yields NaN or a truncated number; copy-paste of whitespace into the field; negative value entered manually.","commonSituations":"Form field not validated before calibration; locale-specific number formatting breaking parseFloat; default empty string treated as 0.","solutions":["Validate the real-distance input is a positive finite number before calling calculateCalibratedScale.","Normalize locale separators (replace comma with dot) before parsing.","Disable the calibration button until a valid positive number is entered.","Show inline field validation with the accepted format."],"exampleFix":"// before\nconst scale = calculateCalibratedScale(pdfDistancePts, realDistance, unit);\n\n// after\nconst real = Number(String(realDistance).replace(\",\", \".\"));\nif (!Number.isFinite(real) || real <= 0) {\n  throw new Error(\"Enter a positive real-world distance (e.g. 10 cm).\");\n}\nconst scale = calculateCalibratedScale(pdfDistancePts, real, unit);","handlingStrategy":"validation","validationCode":"const real = Number(String(realDistance).replace(\",\", \".\"));\nif (!Number.isFinite(real) || real <= 0) {\n  throw new Error(\"Enter a positive real-world distance (e.g. 10 cm).\");\n}\nconst scale = calculateCalibratedScale(pdfDistancePts, real, unit);","typeGuard":"const isValidRealDistance = (d: unknown): d is number =>\n  typeof d === \"number\" && Number.isFinite(d) && d > 0;","tryCatchPattern":null,"preventionTips":["Normalize locale decimal separators before parsing.","Disable the calibration button until a valid positive number is entered.","Show inline field validation with the accepted format."],"tags":["validation","measurement","calibration","user-input","i18n"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}