Skip to content

feat: reject ref and PdfDocument methods with coded PdfMethodErrors - #73

Merged
jkasprzyk17 merged 2 commits into
mainfrom
feat/method-error-codes
Oct 20, 2026
Merged

jkasprzyk17 merged 2 commits into
mainfrom
feat/method-error-codes

Conversation

@jkasprzyk17

@jkasprzyk17 jkasprzyk17 commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #65.

What changes

The ref's promise methods (getOutline, getPageSizes, renderPage, print, getFormFields, setFormFieldValues, exportDocument) and PdfDocument's reads now reject with a PdfMethodError:

try {
  await pdf.current?.getFormFields();
} catch (error) {
  if (error instanceof PdfMethodError && error.code === 'not-loaded') {
    // try again after onLoad
  }
}
  • code is a PdfMethodErrorCode, the same on both platforms: not-loaded, closed, invalid-argument, not-supported, not-permitted, busy, io-error, invalid-pdf, out-of-memory, unknown.
  • message is one sentence: no exception class, no stack trace.
  • nativeDescription keeps the platform's text (on Android with the stack trace).
  • PdfMethodErrorCode is a separate union, so apps that switch exhaustively over onError's PdfErrorCode don't break.

docs/api.md lists the codes and when each method rejects with them; the guides name the codes where they describe rejections.

How

The issue's option 2: a coded message. The Nitro specs don't change.

  • Native rejects with [code] message: Swift PdfMethodFailure, Kotlin PdfMethodException.
  • Platform errors get a code from their type: file system errors are io-error, OutOfMemoryError is out-of-memory, parse failures are invalid-pdf.
  • JS parses the message in one function, toPdfMethodError. It reads the first line, after Android's exception class and before the stack trace. The library ships no ProGuard rules, so in minified release builds the class name is renamed, and the parser accepts any class name.
  • A message without a known code becomes unknown.

A JS test checks that the Swift and Kotlin code lists match the TS union.

Same failure, same code

  • A single-choice list box given several options was "not supported on iOS". It is now invalid-argument on iOS too, as on Android. A multi-select list box given several options is still not-supported on iOS.
  • On Android, getOutline and getMetadata for encrypted documents reject with not-supported (new EncryptedPdfException), not invalid-pdf.
  • Android's renderPage width message no longer reads 4096.0.
  • On iOS, a read or export still waiting for its queue when the view closes or its source changes now rejects with closed, as on Android. Before, it resolved with the old document's data. Calls already running finish on both platforms.

Behavior change (release notes)

On Android, error.message no longer holds the exception class and the stack trace; nativeDescription does. Apps that matched on message text should match on code.

Testing

  • JS (bun test, 124 tests): the parser (iOS-shaped, Android-shaped with a stack trace, a renamed class, no code, empty, not an Error), not-loaded before mount, closed after close(), native rejections → codes. Run red before the change.
  • JVM (testDebugUnitTest, 299 tests): PdfMethodException's message format, including the first line printStackTrace writes (fbjni passes that text to JS), the code of each kind of platform failure, form value codes, and closed for work dropped on close.
  • e2e (Maestro, iOS 26.5 simulator and Android 17 emulator):
    • The example's event lines now show code: message. The flows assert codes instead of message regexes.
    • viewer-sources asserts the full one-line message on both platforms.
    • Both platforms pass pdf-document, viewer-sources, viewer-forms, viewer-page-image, viewer-outline, viewer-page-sizes and stress-close-during-work, with no crashes.
    • Some of these flows needed a second run. In each first failure, Maestro's driver didn't start, dropped a "‹ Back" tap, or didn't see a list row that was on screen. None failed on an assertion.
    • The full suite wasn't run.
  • closed on iOS, by hand on both platforms:
    • On "Several sources, base64", long-press "Image" (200 renderPage calls at once), then tap "Swap" right away.
    • Both reject the burst with closed: The document was closed.
    • No e2e flow covers it: iOS renders a page image in a few milliseconds, so the burst ends before Maestro's next tap.

Not done: the agent skill in better-skills; it follows the release.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

The view's promise methods (getOutline, getPageSizes, renderPage, print,
getFormFields, setFormFieldValues, exportDocument) and PdfDocument's reads
rejected with plain Errors: no code to match on, messages that differed
between platforms, and on Android the exception class and the whole stack
trace in the message. They now reject with a PdfMethodError whose code
(PdfMethodErrorCode) is the same on both platforms: not-loaded, closed,
invalid-argument, not-supported, not-permitted, busy, io-error,
invalid-pdf, out-of-memory or unknown. message is one sentence;
nativeDescription keeps the platform's text.

Nitro rejections carry only a message, so native code rejects with
"[code] message" (PdfMethodFailure in Swift, PdfMethodException in
Kotlin) and one JS function parses its first line, after Android's
exception class (renamed in minified builds) and before the stack trace.
Platform errors are coded by type: file system errors are io-error,
OutOfMemoryError out-of-memory, parse failures invalid-pdf, and the
outline and metadata of encrypted documents on Android not-supported.
The Nitro specs are unchanged.

The same failure has the same code: a single-choice list box given
several options is invalid-argument on iOS too (it was "not supported on
iOS"), and Android's renderPage width message no longer reads "4096.0".
On iOS, a read or export still waiting for its queue when the view closes
or its source changes rejects with closed, as on Android, instead of
resolving with the old document's data.

The example's event lines show code and message, and the e2e flows match
codes instead of message regexes.

Behavior change: on Android, error.message no longer holds the exception
class and the stack trace (nativeDescription does). Apps that matched on
message text should match on code.

Closes #65
@jkasprzyk17 jkasprzyk17 added enhancement New feature or request javascript Pull requests that update javascript code swift The Swift / iOS native layer (package/ios) kotlin The Kotlin / Android native layer (package/android) labels Oct 20, 2026
@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: a91c6d29-109b-4467-a997-2d02f7cd2a0c
📥 Commits

Reviewing files that changed from the base of the PR and between f4b50b2 and 772e4fc.

📒 Files selected for processing: 49
  • ARCHITECTURE.md
  • README.md
  • docs/api-design.md
  • docs/api.md
  • docs/guides/forms.md
  • docs/guides/page-images-and-documents.md
  • docs/guides/printing.md
  • docs/guides/sources-and-loading.md
  • docs/limitations.md
  • example/describeError.ts
  • example/e2e/pdf-document.yaml
  • example/e2e/stress-close-during-work.yaml
  • example/e2e/viewer-forms.yaml
  • example/e2e/viewer-sources.yaml
  • example/screens/DocumentsScreen.tsx
  • example/screens/FormBar.tsx
  • example/screens/ViewerScreen.tsx
  • package/android/src/main/java/com/margelo/nitro/betterpdf/Bitmap+writeToCache.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/DocumentReads+js.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/DocumentReads.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/DocumentSources.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/FormFieldEntry+values.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/HybridBetterPdfDocument.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/HybridBetterPdfView.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/PageImageRequest.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/PdfDocumentSession.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/PdfMethodException.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/SerialWorker.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/outline/PdfDocumentReader.kt
  • package/android/src/main/java/com/margelo/nitro/betterpdf/outline/PdfFormatException.kt
  • package/android/src/test/java/com/margelo/nitro/betterpdf/FormValuesTest.kt
  • package/android/src/test/java/com/margelo/nitro/betterpdf/PdfDocumentSessionTest.kt
  • package/android/src/test/java/com/margelo/nitro/betterpdf/PdfMethodExceptionTest.kt
  • package/ios/DisplayedDocument.swift
  • package/ios/DocumentForm+setValues.swift
  • package/ios/HybridBetterPdfDocument.swift
  • package/ios/HybridBetterPdfView.swift
  • package/ios/PDFPage+renderImage.swift
  • package/ios/PageImageRequest.swift
  • package/ios/PdfMethodFailure.swift
  • package/src/PdfDocument.test.ts
  • package/src/PdfDocument.ts
  • package/src/PdfMethodError.test.ts
  • package/src/PdfMethodError.ts
  • package/src/PdfView.test.tsx
  • package/src/PdfView.tsx
  • package/src/formFields.ts
  • package/src/index.ts
  • package/src/types/PdfMethodErrorCode.ts

Included review availability: This review used your included allowance. 3 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

📝 Summary

Summary by CodeRabbit

  • New Features

    • Added typed method errors with stable, cross-platform codes for document and viewer operations.
    • Exposed PdfMethodError and PdfMethodErrorCode through the public API.
    • Error details now include consistent messages and, when available, native descriptions.
  • Bug Fixes

    • Improved reporting for closed or unloaded documents, invalid arguments, unsupported operations, permissions, printing, I/O, and invalid PDFs.
    • Form validation now distinguishes invalid values, read-only fields, and unsupported operations.
  • Documentation

    • Updated API and feature guides with method-error behavior and operation-specific error codes.

Method calls from PdfViewRef and PdfDocument now reject with PdfMethodError and stable cross-platform codes. Native implementations classify failures, and the example and documentation report the coded errors.

Changes: Typed method error contract

Layer / File(s) Summary
JavaScript error contract and API
package/src/PdfMethodError.ts, package/src/types/PdfMethodErrorCode.ts, package/src/PdfView.tsx, package/src/PdfDocument.ts, package/src/formFields.ts, package/src/index.ts, package/src/*.test.ts, package/src/PdfView.test.tsx, docs/api-design.md, docs/api.md, docs/guides/*, docs/limitations.md, README.md
The package adds PdfMethodError and PdfMethodErrorCode, parses coded native messages, and wraps ref and document methods. API references define the error codes and their conditions. Tests cover parsing, wrappers, and native code consistency.
Android method failures
package/android/src/main/java/com/margelo/nitro/betterpdf/*.kt, package/android/src/main/java/com/margelo/nitro/betterpdf/outline/*.kt, package/android/src/test/java/com/margelo/nitro/betterpdf/*Test.kt
Android document, view, form, image, and printing failures use categorized PdfMethodException errors. Tests assert error codes and exception conversion behavior.
iOS method failures
package/ios/*.swift
iOS operations use categorized PdfMethodFailure errors. DocumentLifetime tracks whether a displayed document has ended, and queued work reports a closed-document error when that occurs.
Documentation and example reporting
ARCHITECTURE.md, example/describeError.ts, example/screens/*.tsx, example/e2e/*.yaml
The architecture documentation lists the error-mapping files. Example screens use shared error formatting, and end-to-end expectations check coded errors.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant PdfViewRef
  participant HybridBetterPdfView
  participant PdfMethodError
  App->>PdfViewRef: Call a promise method
  PdfViewRef->>HybridBetterPdfView: Invoke native operation
  HybridBetterPdfView-->>PdfViewRef: Reject with coded native error
  PdfViewRef->>PdfMethodError: Parse code and message
  PdfMethodError-->>App: Return typed method error
Loading
Merge Risk: ⚪ Minimal · up to 772e4

This change makes method rejections carry stable error codes on both platforms. No concrete merge-blocking issue was identified from the supplied evidence.

Pre-merge checks: Passed 5 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 42.25% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 71 functions across 36 files. (13 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 5 passed
Check name Status Explanation
Title check Passed The title uses the required feature prefix and clearly describes the main change. It exceeds the ideal 50-character target at 67 characters, but remains specific and descriptive.
Description check Passed The description directly explains the coded PdfMethodError changes, affected APIs, platform behavior, documentation, and testing.
Linked Issues check Passed PR #73 implements the coding requirements in open issue #65. The seven view methods and four PdfDocument reads use PdfMethodError with the separate PdfMethodErrorCode union. Swift and Kotlin emi…
Out of Scope Changes check Passed The reviewed changes stay within issue #65. Native exception mapping, lifecycle handling, JavaScript error conversion, tests, documentation, example error formatting, and e2e assertion updates directl…
Security Check Passed No medium-, high-, or critical-severity vulnerability was introduced. The PR adds error classification and promise wrappers. It does not add network access, authorization changes, deserialization, or …
Full details: Linked Issues check

Explanation

PR #73 implements the coding requirements in open issue #65. The seven view methods and four PdfDocument reads use PdfMethodError with the separate PdfMethodErrorCode union. Swift and Kotlin emit coded failures, and JavaScript normalizes them with one parser. The implementation preserves nativeDescription, removes Android stack traces from message, aligns platform codes, and handles closed documents. docs/api.md documents method codes. The e2e flows assert coded output. JS, JVM, and focused e2e tests cover the requested behavior.

Full details: Out of Scope Changes check

Explanation

The reviewed changes stay within issue #65. Native exception mapping, lifecycle handling, JavaScript error conversion, tests, documentation, example error formatting, and e2e assertion updates directly support coded method errors. The encrypted-document classification and cross-platform form and close behavior also implement the issue's stated same-failure requirements. No unrelated feature or cleanup change is demonstrated.

Full details: Security Check

Explanation

No medium-, high-, or critical-severity vulnerability was introduced. The PR adds error classification and promise wrappers. It does not add network access, authorization changes, deserialization, or new file-path behavior. Export path checks remain unchanged on both platforms. Native descriptions retain error text and Android stack traces by design, matching the documented API and existing Android rejection behavior. No prior security findings were supplied.

Full details: Docstring Coverage

Explanation

Docstring coverage is 42.25% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 71 functions across 36 files. (13 skipped: 13 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.

Comment @coderabbitai help to get the list of available commands.

@jkasprzyk17
jkasprzyk17 merged commit 7d5f16f into main Oct 20, 2026
5 checks passed
@jkasprzyk17
jkasprzyk17 deleted the feat/method-error-codes branch October 20, 2026 22:34
jkasprzyk17 added a commit to duquerson/react-native-better-pdf that referenced this pull request Oct 21, 2026
Since gmi-software#73 the ref's promise methods reject with a PdfMethodError, and apps
match on its code rather than the message.
@jkasprzyk17 jkasprzyk17 mentioned this pull request Oct 21, 2026
5 of 8 tasks
jkasprzyk17 added a commit that referenced this pull request Oct 21, 2026
* fix: handle null, undefined and malformed sources gracefully (#66)

* fix: harden invalid source reporting

* fix: clarify invalid source diagnostics

* fix: keep overlay context when source is empty

* docs: mark source as optional and nullable in api-design

* docs: name the not-loaded code for an unmounted PdfView

Since #73 the ref's promise methods reject with a PdfMethodError, and apps
match on its code rather than the message.

---------

Co-authored-by: caja_autoservicio <caja.prat@cademartori.cl>
Co-authored-by: Jakub Kasprzyk <kasprzykjakub@proton.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request javascript Pull requests that update javascript code kotlin The Kotlin / Android native layer (package/android) swift The Swift / iOS native layer (package/ios)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ref and PdfDocument methods reject with plain Errors: no code to match on, and on Android the message is a Java stack trace

1 participant