Summary
PdfViewer throws Unsupported operation: Infinity or NaN toInt from
_PdfViewerState._createRealSizePartialImage during real-size partial
rendering, when the computed pageScale is non-finite (Infinity or NaN).
The value reaches .toInt() unguarded and throws.
This is a distinct path from the two existing reports:
Environment
- pdfrx: 2.4.7 (latest at time of writing)
- Flutter 3.44.6 / Dart 3.x
- Observed on iOS; the code path is platform-independent
- Non-fatal for us (thrown from an internal
Timer), but frequent in production
(hundreds of events across ~120+ users / 90 days) and it fails the high-res
render + floods error tracking.
Captured stack (top frames)
#0 _PdfViewerState._createRealSizePartialImage (package:pdfrx/src/widgets/pdf_viewer.dart)
#1 _PdfViewerState._requestRealSizePartialImage.<anonymous closure> (package:pdfrx/src/widgets/pdf_viewer.dart)
#2 TickerFuture.whenCompleteOrCancel.thunk (package:flutter/src/scheduler/ticker.dart)
#3 _Timer._runTimers (dart:isolate-patch/timer_impl.dart)
Root cause (line numbers for 2.4.7)
pageScale divides by the page dimensions:
// pdf_viewer.dart ~L1567
final pageScale =
scale * max(rect.width / page.width, rect.height / page.height);
if (!enableLowResolutionPagePreview || pageScale > previewScaleLimit) {
_requestRealSizePartialImage(cache, page, pageScale, targetRect); // ~L1570
}
If page.width or page.height is 0 the division is Infinity; 0 / 0 is
NaN. A non-finite scale reaches the same point. It is then used unguarded:
// pdf_viewer.dart ~L1807-1810, in _createRealSizePartialImage
final x = (inPageRect.left * scale).toInt();
final y = (inPageRect.top * scale).toInt();
final width = (inPageRect.width * scale).toInt(); // throws on Infinity/NaN
final height = (inPageRect.height * scale).toInt();
double.toInt() throws UnsupportedError: Infinity or NaN toInt for a
non-finite receiver.
Suggested fix
A finite guard before the conversion — at the call site:
if (!pageScale.isFinite) return; // before _requestRealSizePartialImage(...)
or inside _createRealSizePartialImage, before the .toInt() block:
if (!scale.isFinite) return null;
Guarding the page-dimension division (page.width == 0 || page.height == 0)
would remove the non-finite value at the source.
Repro notes
Data/timing dependent — reproduces with a page reporting a zero dimension, or
when the viewer is laid out in a transiently zero-sized box while a zoom render
is requested. The guard fixes it regardless of which input goes non-finite.
Related: #587, #550
Summary
PdfViewerthrowsUnsupported operation: Infinity or NaN toIntfrom_PdfViewerState._createRealSizePartialImageduring real-size partialrendering, when the computed
pageScaleis non-finite (Infinity or NaN).The value reaches
.toInt()unguarded and throws.This is a distinct path from the two existing reports:
round10BitFrac) — fixed in 2.2.19, different code.InteractiveViewer._onScaleEnd),closed without a located root cause. This report pins a concrete location for
the
_createRealSizePartialImagevariant, which is still unguarded in 2.4.7.Environment
Timer), but frequent in production(hundreds of events across ~120+ users / 90 days) and it fails the high-res
render + floods error tracking.
Captured stack (top frames)
Root cause (line numbers for 2.4.7)
pageScaledivides by the page dimensions:If
page.widthorpage.heightis0the division isInfinity;0 / 0isNaN. A non-finitescalereaches the same point. It is then used unguarded:double.toInt()throwsUnsupportedError: Infinity or NaN toIntfor anon-finite receiver.
Suggested fix
A finite guard before the conversion — at the call site:
or inside
_createRealSizePartialImage, before the.toInt()block:Guarding the page-dimension division (
page.width == 0 || page.height == 0)would remove the non-finite value at the source.
Repro notes
Data/timing dependent — reproduces with a page reporting a zero dimension, or
when the viewer is laid out in a transiently zero-sized box while a zoom render
is requested. The guard fixes it regardless of which input goes non-finite.
Related: #587, #550