Skip to navigation

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

CodeWhen it fires, and the fixFix
cross-originThe 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 taintedSend the header. If the request needs cookies, pass crossOrigin="use-credentials" to Root. Add the host to connect-src, as in loading images
unsupported-formatThe 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 againTry another copy of the file. Call loadImage yourself with your own decode function, as in loading images, or convert the file to JPEG first
decodeThe 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 againOpen 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-largeA 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 securitySend 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
timeoutA 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 countSend a smaller file or export a smaller maxSize. For a slow network, load the photo yourself with a longer timeout, as in loading images
abortedThe 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 itNothing. Skip this code in your catch
blankThe 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 phonesSet maxSize to 2048 by 2048 or less
no-imageAn 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 abortedDisable 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.

Message
zriz: parts must be inside <Cropper.Root>
Move the part inside Root. A part in a portal still needs Root above it in the React tree
zriz: pass a cropper or render inside <Cropper.Root>
A hook such as useCropperValue or useZoom ran outside Root. Pass it the cropper from useCropper, or move the component inside Root
zriz: no cropper
Root got cropper on its first render and none later. Keep passing the same cropper, or give Root a new key to start a new one
zriz: this is not an export plan
Pass toSharp the plan from getPixelCrop() or a commit, and the size of the same photo, both unchanged. When pixelRect is null, a bad forward, a side that is not a whole number of at least 1, or a crop fully outside the photo throws this. A plan with a pixelRect gets 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.

Message
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-US and options Intl.NumberFormat accepts. 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 Viewport per cropper, and draw a live preview with useCropperFrame, see viewport