Errors & cancelling
Every call that fails rejects with an EngineError. Its code says what went wrong, so you can
handle each case:
import { EngineError, EngineErrorCode } from '@embedpdf/engine';
try {
await page.annotations.update(ref, { contents: 'Done' });
} catch (error) {
if (EngineError.is(error, EngineErrorCode.Forbidden)) {
showMessage('You can only edit your own comments.');
} else if (EngineError.is(error, EngineErrorCode.NotFound)) {
showMessage('This comment was deleted.');
} else {
throw error;
}
}EngineError.is(error, code) checks both that it’s an engine error and that it has that code.
Branch on the code, never on the message: messages are for people and can change.
Cancelling a call#
Every call returns a promise you can cancel. Keep it, and call abort() when you no longer need
the answer:
const rendering = page.render.image({ viewport: { kind: 'width', width: 1600 } });
// The user scrolled past the page:
rendering.abort();The promise rejects right away with code Aborted, and the engine stops the work if it hasn’t
finished. Cancelling a call that already finished does nothing.
try {
const image = await rendering;
} catch (error) {
if (EngineError.is(error, EngineErrorCode.Aborted)) return; // we cancelled it
throw error;
}Only the promise the call returned has abort(): rendering.then(…) gives a plain promise. Keep
the original.
A time limit is a cancel on a timer:
const listing = doc.annotations.list();
const timer = setTimeout(() => listing.abort(), 5000);
try {
return await listing;
} finally {
clearTimeout(timer);
}When the rest of your code cancels with an AbortController (a fetch, a framework’s cleanup),
tie the call to its signal with abortWith():
const controller = new AbortController();
const image = await page.render.image().abortWith(controller.signal);
// later, in your cleanup:
controller.abort();The call is cancelled when the signal aborts, or at once if it already has.
Error codes#
The codes you’ll handle most:
| Code | What happened |
|---|---|
Forbidden | The user doesn’t have the permission. error.details.required names it. |
NotFound | The page, annotation or field isn’t there (anymore). |
InvalidArg | Something you passed isn’t valid. The message says what. |
Aborted | You cancelled the call. |
DocPasswordRequired | The file needs a password. See Opening documents. |
DocPasswordIncorrect | unlock() got a wrong password. |
DocOpenFailed | The file isn’t a PDF, or is too damaged to open. |
PayloadTooLarge | An import or export is past a limit. error.details has the limit and max. |
ProtectedDocument | A signature in the document forbids this change. |
ObjectNumberUnavailable | A create named an object number this session doesn’t hold, or used one twice. |
ChangeConflict | A change’s expect didn’t match the document. Nothing was written. See Changes & undo. |
UndoUnavailable | The change can’t be undone anymore. error.details.reason says why: 'final-change' or 'expired'. |
LayerFull | The document has as many objects as a PDF file should; a compacted copy starts afresh. |
Good to know#
Every code#
| Code | What happened |
|---|---|
DocNotOpen | The document was closed. |
RuntimeUnavailable | The engine was destroyed, or the browser lacks something it needs. |
MalformedPdf | The file opened, but part of it is too damaged to use. |
NotImplemented | This engine can’t do this (yet). |
SigningPending | A signature is being made; finish or cancel it first. |
SigningExpired | The signature took too long; start it again. |
SigningVersionMismatch | The document changed while the signature was being made; start it again. |
SignatureRefused | This field can’t be signed. The message says why. |
StaleBase | The document was signed elsewhere; this copy can be edited but not signed. |
IdempotencyKeyReused | An opId that already named another change was used again. |
WireFormat | The server sent something the engine didn’t expect. |
Unknown | Anything else. Please report it. |
details#
Some errors carry more in error.details: the missing permission for Forbidden, the field for
InvalidArg, the limit for PayloadTooLarge. Log error.toJSON() to see everything an error
has.
Your feedback goes directly to the documentation team.