Errors and warnings
lamina reports problems in two ways:
- An error stops the call. In TypeScript it’s a
LaminaError. In Rust it’slamina::Error. - A warning means the call went ahead, but something in the file was repaired, dropped or approximated:
doc.warningsin TypeScript,doc.warnings()in Rust.
Both have the same fields on every surface: code, kind (input, limit, usage, state, io, …), message, hint, location, data and docsUrl. toJSON() gives the same object in TypeScript as serde does in Rust.
- Branch on
code, never onmessage.isLaminaError(e, "wrong-password")narrows the type. kindsorts errors by who can fix them. For example, a server returns a 4xx forinputandlimitand a 5xx for the rest. The Worker quick start does exactly that.- Text from the document is untrusted. It’s never in
messageorhint. It goes only indata.
// Open bytes from someone else: a password, tighter limits than the defaults, and the outcome as// a value rather than an exception (the docs site's encrypted files, limits and errors guides).// It has no Rust golden: it writes nothing; test/examples.test.ts checks what it reports.import { Document, isLaminaError } from "@lamina/pdf";
/** What opening a file gave: its page count and warning codes, or why it didn't open. */export type Opened = | { readonly ok: true; readonly pages: number; readonly warnings: readonly string[] } | { readonly ok: false; readonly code: string; readonly hint: string | undefined };
/** * Opens `bytes` with `password` (empty: none) and limits for an upload endpoint: decoded streams * of at most 16 MiB each and 64 MiB in all. Needs `init()`. */export function openUntrusted(bytes: Uint8Array, password = ""): Opened { try { const doc = Document.open(bytes, { ...(password === "" ? {} : { password }), limits: { maxStreamDecoded: 16 << 20, maxDecodedTotal: 64 << 20 }, }); try { // Repairs and dropped values are warnings: the file opened, but not exactly as written. return { ok: true, pages: doc.pageCount, warnings: doc.warnings.map((w) => w.code) }; } finally { doc.free(); } } catch (e) { // `password-required`, `wrong-password`, `not-pdf`, `limit-exceeded`, …: a coded LaminaError // whose message and hint never contain text from the file (ADR 0026 §4). if (isLaminaError(e)) return { ok: false, code: e.code, hint: e.hint }; throw e; }}Every code, with its kind, summary and hint, is listed in the code reference, which is generated from fixtures/codes.json.