Errors
Every error zriz throws or reports, when it happens and how to fix it.
Where errors arrive
Root calls onError with a ZrizError when a photo cannot load. ZrizError comes from @zriz/core/dom, like loadImage and exportCrop. attachImage throws no-image at once when the photo was already freed. loadImage and exportCrop reject, so catch them where you call them:
import type { Cropper } from "@zriz/core";
import { exportCrop, ZrizError } from "@zriz/core/dom";
export const save = async (
cropper: Cropper,
signal?: AbortSignal
) => {
try {
const { blob } = await exportCrop(cropper, { signal });
return blob;
} catch (error) {
if (
error instanceof ZrizError &&
error.code === "aborted"
) {
return null;
}
throw error;
}
};Every ZrizError has a code from the table below, and its message starts with zriz:. The one exception is a decode function you pass to loadImage: when it throws, loadImage rejects with your own error as it is.
Codes
| Code | When it fires, and the fix | Fix |
|---|---|---|
| cross-origin | The server sent the photo without Access-Control-Allow-Origin, the network dropped, connect-src in a content security policy blocked the URL, or an img, video, canvas or ImageBitmap you pass is tainted | Send the header. If the request needs cookies, pass crossOrigin="use-credentials" to Root. Add the host to connect-src, as in loading images |
| unsupported-format | The browser could not decode a HEIC, JPEG XL or TIFF file, because it does not support the format or the file is damaged, either on load or when an export decodes the original again | Try another copy of the file. Call loadImage yourself with your own decode function, as in loading images, or convert the file to JPEG first |
| decode | The URL answered with an error status, the file cannot be read, the file is cut short, the bytes are not an image, Safari refused a BMP with a v4 or v5 header, a zriz chunk failed to download, an img, video or canvas you pass cannot be read, a video has no current frame, img-src in a content security policy blocked an SVG or a display-p3 export, the browser gave no 2D canvas, or an export could not decode the original again | Open the URL and check the response. If you are offline, try again once the network is back. If the same error comes back, reload the page, because a browser can keep a failed chunk until then. Wait for loadeddata before you pass a video. Loading images lists the img-src sources |
| too-large | A file's header or decoded image has more pixels than maxPixels, 268402689 by default. This also covers a decode function, but not an img, video, canvas, OffscreenCanvas or ImageBitmap source. An SVG fails with it when drawing it would freeze the page, see security | Send a smaller file. To open it anyway, load the photo yourself with a higher maxPixels, as in loading images. For an SVG, send a simpler file or a PNG of it |
| timeout | A URL sent no bytes for 15 s, a photo took over 15 s to decode after its last byte, or an export took over 30 s. Time spent waiting behind other photos or exports does not count | Send a smaller file or export a smaller maxSize. For a slow network, load the photo yourself with a longer timeout, as in loading images |
| aborted | The signal you passed fired, a new photo or a detach came while the export code was still downloading, or a photo from an img, video, canvas, SVG or decode function was freed while the export waited its turn. A new photo after that does not stop the export and you get the old crop, so abort with your own signal when the photo changes. Root also aborts its own load when src changes and never reports it | Nothing. Skip this code in your catch |
| blank | The browser drew an empty canvas at the export size, then at half and a quarter of it. This is the canvas memory limit, mostly on phones | Set maxSize to 2048 by 2048 or less |
| no-image | An export ran before a photo loaded, the app attached a photo that was already freed, or the app has two copies of @zriz/core and the export came from the one that never got the photo. A detach before the export call, even with an aborted signal, gives this code. A detach in the same tick right after the call gives aborted | Disable the export button until onLoad fires. Load a freed photo again. Keep @zriz/core at the same version as @zriz/react |
Thrown errors
These are plain Error objects that React shows in its error overlay. The first three mean a part or hook cannot find its cropper. toSharp throws the last one as a RangeError, usually on your server.
- zriz: parts must be inside <Cropper.Root>
- Move the part inside
Root. A part in a portal still needsRootabove it in the React tree - zriz: pass a cropper or render inside <Cropper.Root>
- A hook such as
useCropperValueoruseZoomran outsideRoot. Pass it the cropper fromuseCropper, or move the component insideRoot - zriz: no cropper
Rootgotcropperon its first render and none later. Keep passing the same cropper, or giveRoota newkeyto start a new one- zriz: this is not an export plan
- Pass
toSharpthe plan fromgetPixelCrop()or acommit, and the size of the same photo, both unchanged. WhenpixelRectisnull, a badforward, a side that is not a whole number of at least 1, or a crop fully outside the photo throws this. A plan with apixelRectgets no check, so recompute the plan on your server as server crop does
Console warnings
In development, Area, Dial and Zoom each warn once when nothing names them, Dial and Zoom warn once for a locale or format the browser refuses, and a second visible Viewport on one cropper warns once. The message has the part's name. Production builds print nothing.
- zriz: <Cropper.Area> needs aria-label or aria-labelledby. zriz ships no words, so screen readers get nothing otherwise.
- Name the part. Accessibility shows how to label each part
- zriz: <Cropper.Dial> ignores a locale or format the browser refuses. A refused locale falls back to the browser's, and a refused format to the default value text.
- Pass a locale tag like
en-USand optionsIntl.NumberFormataccepts. Until then a refused locale speaks in the browser's locale and a refused format speaks the default text - zriz: one <Cropper.Viewport> per cropper. A second one takes over the layout. Draw a live preview with useCropperFrame.
- Render one
Viewportper cropper, and draw a live preview withuseCropperFrame, see viewport