{"record":{"id":"65ee9f5d710d0849","repo":"tui-cs/Terminal.Gui","slug":"zoom-level-must-be-a-finite-number","errorCode":null,"errorMessage":"Zoom level must be a finite number.","messagePattern":"Zoom level must be a finite number\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Views/ImageView/ImageView.Input.cs","lineNumber":68,"sourceCode":"        _centerX = centerX;\n        _centerY = centerY;\n        ClampCenter ();\n\n        if (Math.Abs (previousCenterX - _centerX) < double.Epsilon && Math.Abs (previousCenterY - _centerY) < double.Epsilon)\n        {\n            return false;\n        }\n\n        InvalidateScaledImage ();\n\n        return true;\n    }\n\n    private bool SetZoomLevel (double zoomLevel, Point? anchor)\n    {\n        if (double.IsNaN (zoomLevel) || double.IsInfinity (zoomLevel))\n        {\n            throw new ArgumentOutOfRangeException (nameof (zoomLevel), @\"Zoom level must be a finite number.\");\n        }\n\n        double previousZoomLevel = _zoomLevel;\n        double clampedZoomLevel = Math.Clamp (zoomLevel, GetMinimumZoomLevel (), MAX_ZOOM_LEVEL);\n\n        if (Math.Abs (previousZoomLevel - clampedZoomLevel) < double.Epsilon)\n        {\n            return false;\n        }\n\n        if (anchor is { } position && TryMapViewportPointToSourceCenter (position, out double sourceX, out double sourceY))\n        {\n            _zoomLevel = clampedZoomLevel;\n            SetCenterForAnchor (position, sourceX, sourceY);\n        }\n        else\n        {\n            _zoomLevel = clampedZoomLevel;","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Views/ImageView/ImageView.Input.cs#L50-L86","documentation":"Thrown by ImageView.SetZoomLevel when the supplied zoomLevel is NaN or infinite. Zoom is a multiplier applied to source pixel dimensions and used in clamp/compare math, so a non-finite value would poison layout and rendering arithmetic. The value is clamped to [GetMinimumZoomLevel(), MAX_ZOOM_LEVEL] after the check, so only truly broken numbers (division-by-zero results, uninitialised doubles) reach the guard.","triggerScenarios":"Computing zoomLevel from a ratio where the denominator is zero or infinity (e.g. image.Width == 0 -> width/0.0); reading zoom from parsed/config data that defaulted to NaN; chaining double transformations that accumulate NaN via 0*Inf.","commonSituations":"Auto-fit logic that divides by an image dimension before the image has loaded; JSON/deserialised config where the field was never set; math derived from an empty viewport size.","solutions":["Guard the divisor before computing zoom: if (image.Width == 0) return; double zoom = viewport / (double)image.Width;","Sanitise external input with double.IsFinite(zoomLevel) before calling SetZoomLevel or setting ZoomLevel.","Default uninitialized zoom fields to a finite sentinel (e.g. 1.0) rather than leaving them as NaN.","Use the public clamped API (ZoomLevel property) which routes through the same guard, so fix the source of the bad value upstream."],"exampleFix":"// before\ndouble zoom = viewportWidth / (double)image.Width; // NaN if Width==0\nimageView.ZoomLevel = zoom;\n\n// after\ndouble zoom = image.Width > 0 ? viewportWidth / (double)image.Width : 1.0;\nimageView.ZoomLevel = zoom;","handlingStrategy":"validation","validationCode":"double zoom = ComputeZoom();\nif (!double.IsFinite(zoom))\n{\n    zoom = 1.0; // safe default\n}\nimageView.ZoomLevel = zoom;","typeGuard":"static bool IsValidZoom(double z) => double.IsFinite(z) && z > 0;","tryCatchPattern":null,"preventionTips":["Check the divisor before dividing when computing zoom from dimensions.","Sanitise deserialised/config zoom values with double.IsFinite before use.","Default numeric fields to a finite sentinel, never NaN."],"tags":["imageview","numeric","validation","precondition"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}