Skip to content

Browser errors and limits

The browser package separates immutable export failures, prepared manifest and query failures, application port failures, and cancellation. Handle the family that owns the failed operation.

The partial handling example assumes operation(), reportExportFailure(), and reportPreparedFailure() belong to the application:

ts
import { isNotebookExportError, type NotebookExportError } from "@marimo-team/marimo-export";
import { isPreparedAbort, isPreparedExportError } from "@marimo-team/marimo-export/prepared";

try {
  await operation();
} catch (error) {
  if (isPreparedAbort(error)) return;
  if (isNotebookExportError(error)) {
    reportExportFailure(error.code, error.details, error.cause);
    return;
  }
  if (isPreparedExportError(error)) {
    reportPreparedFailure(error.code, error.cause);
    return;
  }
  throw error;
}

NotebookExportError

ts
class NotebookExportError extends Error {
  readonly code: NotebookExportErrorCode;
  readonly details: JsonObject | undefined;
  readonly cause: unknown;
}

Construct it as new NotebookExportError(code, message, { cause, details }). The constructor validates the code and message, converts details to frozen portable JSON, then freezes the error. An unknown code or non-string message raises TypeError.

isNotebookExportError(value) recognizes the versioned global brand across iframes and separately bundled package copies. It also checks the public name, message, code, and optional details. Inaccessible or invalid properties make the guard return false.

Reader error codes

CodeOperation and meaningCommon recovery
abortAn export operation or output load lost caller authorityIgnore stale work or retry with a live signal
asset_invalidA BlobAsset MessagePack envelope or its descriptor agreement is invalidRebuild or replace the export
decode_failedNative framing, a snapshot parser, or the selected loader rejected dataConfirm the producer and loader versions, then rebuild the representation
integrity_failedDeclared size, observed size, SHA-256, or Web Crypto verification failedStop using the artifact and redeploy from a verified source
loader_ambiguousMore than one registered loader accepts the outputNarrow media-type predicates or pass one explicit loader
loader_invalidA loader is malformed, throws in accepts(), or returns a non-boolean acceptance valueCorrect the loader contract
loader_unavailableNo loader accepts the output codec and media typeImport the matching loader and its peer runtime
output_not_foundAn output name is absent from the selected stateInspect outputNames and use a published name
output_representation_changedOne output name changes codec or media type across statesRebuild with one stable representation per output
export_invalidThe index schema, shape, values, names, descriptors, or state fingerprints are invalidRegenerate the export with a compatible producer
export_noncanonicalindex.json parses but its exact bytes are not canonical JSONRegenerate the index through marimo-export
read_failedFetch, response status, body availability, or stream reading failedCheck the URL, CORS, authentication, deployment, and network
read_limit_exceededAn index, asset, or complete verification exceeds its byte budgetInspect the declared size, then raise a caller limit only when the artifact is trusted and memory is available
state_input_invalidA complete vector or sparse patch has invalid values or input namesCompare the object with inputNames
state_not_foundAn authored state alias is absentInspect each state's aliases array
state_unavailableA valid complete input vector is absent from this exportChoose an exported state or publish another export

details is bounded diagnostic context. Its fields vary by failure site. Common fields include output name, codec, media type, requested and available names, path, response status, declared and observed bytes, byte limits, expected and observed digests, and input key sets. Branch on code first and treat additional fields as optional.

An error thrown by a loader passes through unchanged when it is already a branded NotebookExportError. Another loader failure becomes decode_failed. An abort-shaped loader failure becomes abort and retains its source as cause.

PreparedExportError

ts
type PreparedExportErrorCode =
  "manifest_invalid" | "manifest_read_failed" | "query_ambiguous" | "query_miss";

class PreparedExportError extends Error {
  readonly code: PreparedExportErrorCode;
  readonly cause: unknown;
  constructor(
    code: PreparedExportErrorCode,
    message: string,
    options?: { readonly cause?: unknown },
  );
}
CodeMeaningRecovery
manifest_invalidThe document, identity, export URL, input vector, fingerprint, or control binding is invalidFix the route or republish a matching manifest and export
manifest_read_failedThe manifest request, response, stream, or byte limit failedCheck routing, CORS, authentication, response status, and body size
query_ambiguousOne query text matches more than one typed exported valueUse an unambiguous state control or change the exported input domain
query_missA recognized query parameter is repeated or matches no exported valueSupply one value whose text matches the exported domain

isPreparedExportError() recognizes a frozen, branded prepared error across package copies. Construction validates the code and message and freezes the result. Prepared controller state resolution can still raise NotebookExportError. PreparedStatePort can raise an application error. A transition failure followed by a restoration failure raises AggregateError with both causes.

Cancellation

isPreparedAbort(value) recognizes:

  • a DOMException named AbortError
  • an Error named AbortError
  • a NotebookExportError with code abort

Prepared APIs preserve an Error or DOMException used as an abort reason. Another reason becomes a DOMException named AbortError.

Cancellation removes stale commit authority and asks cooperative work to stop. Browser dynamic imports, Parquet decoding, and renderer work can continue after the caller receives an abort. Application ports must check the signal before visible commit and clean up late or staged resources.

Default and hard limits

Reader and manifest limits

BoundaryLimitBehavior
index.json body16 MiBopenExport() raises read_limit_exceeded before or during the body read
index.json parsed values2,000,000Strict parsing rejects a larger document
One output asset, default caller limit512 MiBExportOutput.load() and verify() use this when maxBytes is absent
One output asset, hard caller limit2,147,483,647 bytesA larger maxBytes raises TypeError
Complete verification, default aggregate2 GiBDeclared unique asset bytes are checked before any verification fetch
Prepared manifest body256 KiBFetch rejects a larger declared or observed body
Prepared export_url8,192 UTF-8 bytesManifest parsing rejects an empty or larger value
Prepared polling0, or 250 through 60,000 msZero disables polling. Other values outside the range fail parsing

maxBytes must be a positive safe integer. maxTotalBytes must be a non-negative safe integer. A value of zero is valid for maxTotalBytes and allows verification only when the export has no assets.

Producer and local-reader defaults are narrower at 64 MiB per asset and 512 MiB across one export. A browser limit is a consumer memory policy and does not expand what a standard producer writes.

Format and loader limits

BoundaryLimit
Export input, output, version, and filename text255 UTF-8 bytes, with field-specific character rules
Control object ID1,024 UTF-8 bytes
Control path256 steps
Descriptor provenance text2,048 UTF-8 bytes
BlobAsset metadata256 KiB of canonical JSON
Media type1,024 printable ASCII bytes
One declared descriptor asset2,147,483,647 bytes
marimo snapshot values2,000,000
NumPy header1 MiB
NumPy typed-array length4,294,967,295 elements
Arrow LZ4 decompressed buffer512 MiB
AnyWidget page module definitions1,024
AnyWidget external module URL8,192 UTF-8 bytes
AnyWidget data URL media type1,024 UTF-8 bytes

Export format defines field shapes and producer limits. Portable JSON defines its separate 256-level and 100,000-value limits.

Browser requirements

Opening and loading use these web platform capabilities:

  • the Fetch API and readable response streams
  • strict TextEncoder and TextDecoder support
  • SubtleCrypto.digest() with SHA-256
  • AbortController, AbortSignal, and AbortSignal.throwIfAborted()
  • URL, Object.hasOwn(), frozen objects, and structuredClone()
  • typed arrays, including BigInt typed arrays for 64-bit NumPy integers

Mounts can also require the DOM, Blob and object URL APIs, dynamic module import, canvas or SVG support, and the capabilities of a selected peer runtime.

Web Crypto is available in a secure context. Serve an application over HTTPS or from a browser-recognized local development origin. A missing Web Crypto implementation raises integrity_failed.

The package manifest does not declare a browser-version matrix. Check these capabilities in every supported application browser and run mounted runtime tests for each required loader.

Diagnose common failures

The export cannot be read

Inspect the resolved base and request URLs, response status, CORS response headers, credentials, and response body. NotebookExportError.details.path and optional status identify the failed export object.

The index is invalid or noncanonical

Regenerate the directory with marimo-export. Reformatting, pretty-printing, or appending a newline changes canonical index.json bytes and its identity.

A loader is unavailable

Compare output.codec and output.mediaType.essence with the loader catalog. Install the listed peer beside @marimo-team/marimo-export.

A mount is blocked

Inspect the browser console and the deployed Content Security Policy (CSP). Check Blob module, script origin, style element, image, data, font, and network permissions used by the selected representation.

A state or query cannot resolve

Inspect inputNames, states().map(state => state.inputs), and each state's aliases. Query strings match only values present in that finite domain. A new input vector requires a new export or a Python service.

Released under the Apache 2.0 License.