This page covers the most common problems you may encounter when integrating KPDF into a Compose Multiplatform application. For each issue you’ll find the root cause and a concrete fix, with code examples where they help.Documentation Index
Fetch the complete documentation index at: https://mahmoud-b28887f9.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
openDocumentState stays at Idle
openDocumentState stays at Idle
Cause: After this change,
KPdfViewerState is being recreated on every recomposition because you are building KPdfViewerConfig inline — without remember. Each new config instance causes rememberPdfViewerState to return a brand-new state object, which resets transient flows like openDocumentState before they can deliver a result.Fix: Wrap both source and config in remember so they remain stable across recompositions.openDocumentState will progress through AwaitingSelection → Success (or Cancelled / Error) without resetting mid-flight.PDF loads from URL but fails offline
PDF loads from URL but fails offline
Cause: Once the PDF has been downloaded at least once with a non-zero cache size, KPDF will serve it from the disk cache on subsequent opens — even without a network connection.If you need to keep storage use minimal, set
KPdfSource.Url downloads and renders the PDF over the network. By default, KPDF can cache the downloaded bytes to disk so that subsequent opens work without a network connection.If diskCacheSize is 0, disk caching is disabled, and the document will fail to open when the device is offline.Fix: Set a non-zero diskCacheSize in your config. The value is the maximum number of rendered pages to persist to disk.diskCacheSize to a small positive value (for example 10) rather than 0.Thumbnails are slow or blank
Thumbnails are slow or blank
Cause: KPDF renders thumbnails asynchronously via If a thumbnail enters an error state (for example because a render call fails), you can tap it to retry. KPDF will call
renderPage(). Each thumbnail is a separate render call that runs off the main thread. On low-end devices, or when thumbnailWidth/thumbnailHeight are set too large, render times can be long enough that thumbnails appear blank for several seconds.Fix: Keep thumbnail dimensions reasonable. Values around 92.dp × 128.dp give a good balance between visual quality and render speed.renderPage() again for that page index.Reducing thumbnailWidth and thumbnailHeight is the single most effective way to speed up the strip on constrained hardware.Save flow does nothing / stays at Idle
Save flow does nothing / stays at Idle
Cause: The same root cause as the With a stable viewer state,
openDocumentState issue: KPdfViewerState is being recreated because KPdfViewerConfig is rebuilt inline on every recomposition. When the state resets, the saveState flow reverts to Idle before the platform save dialog can return a result.Fix: Wrap source and config in remember so the viewer state is stable.saveState will progress through the full lifecycle instead of silently resetting.externalOpenState stays at Idle
externalOpenState stays at Idle
Cause: Same root cause as the save and open-document issues: a newly constructed
KPdfViewerConfig on each recomposition recreates the viewer state, which resets externalOpenState to Idle before the platform flow completes.Fix: Stabilize source and config with remember.Zoom controls are disabled
Zoom controls are disabled
Cause: The You can read
zoomIn() and zoomOut() actions disable themselves when currentZoom reaches the bounds defined by zoomRange() in your config. If zoom is also disabled entirely via enableZoom(false), both controls will be inactive regardless of the current zoom level.Fix: Check two things in your config:- Call
enableZoom(true)to enable zoom interaction. - Call
zoomRange(minZoom, maxZoom)with values that give the user room to zoom. IfminZoomequalsmaxZoom, neither button will ever be enabled.
currentZoom to understand the current zoom level at runtime and decide whether to render your own zoom controls in a disabled state.Swipe navigation doesn't work
Swipe navigation doesn't work
exportPdf() returns a failure
exportPdf() returns a failure
Cause: Always handle the
exportPdf() operates on the currently loaded source. If you call it before the document has finished loading — that is, before loadState reaches Ready — it will return a failure because there is no loaded content to export.Fix: Observe loadState and only call exportPdf() once it signals that the document is ready.onFailure branch. Sources that fail to load, are cancelled mid-flight, or encounter a rendering error will all surface through the failure path.If your issue isn’t covered here, open an issue or search existing discussions at github.com/mahmoud947/KPDF.