Reference

Errors & validation

Errors & validation

Failures fall into two kinds, and the kind tells you whose mistake it was. Argument validation throws a plain RangeError before anything reaches WASM — that is a bug in the calling code. libopus failures throw an OpusError — the codec rejected otherwise well-formed input, usually a corrupt or truncated packet.

#RangeError: bad arguments

Every option and buffer is checked up front. A wrong frame size, an out-of-range option, an empty packet, or a CTL request outside the allow-list throws synchronously with a RangeError:

encoder.encode(new Int16Array(123)); // RangeError: wrong sample count
await createEncoder({ channels: 3 }); // RangeError: channels must be 1 or 2

These never reach the WASM boundary, so they cost nothing and carry a precise message. Treat them as programming errors to fix, not conditions to catch at runtime.

#OpusError: the codec rejected it

When libopus itself returns an error code — a malformed packet handed to decode or getPacketInfo, for example — it surfaces as an OpusError:

import { OpusErrorCode, isOpusError } from "libopus-wasm";

try {
  decoder.decode(corruptPacket);
} catch (err) {
  if (isOpusError(err)) {
    if (err.operation === "decode" && err.code === OpusErrorCode.InvalidPacket) {
      // Drop or conceal this corrupt packet.
    }
  }
}
MemberTypeDescription
codenumberThe raw libopus error code (negative).
codeNamestring | undefinedNamed libopus error code, such as "InvalidPacket", when known.
operationstring | undefinedThe call that failed — "decode", "encode", "getPacketInfo", …
messagestringlibopus's own error text, prefixed with the operation and code.

OpusError extends Error, so instanceof Error matches it too. Use isOpusError() when errors may cross package or realm boundaries.

#Empty vs. lost packets

An empty Uint8Array is rejected with a RangeError — a zero-length buffer is not a valid packet. To signal a lost packet to the decoder, pass null (or call decodePacketLoss), which triggers packet-loss concealment instead of an error.

decoder.decode(new Uint8Array(0)); // RangeError — don't do this
decoder.decode(null);              // concealed frame — the right way

#Using a freed handle

Calling any method on an encoder or decoder after free() (or after a using scope exits) throws a plain Error. Allocate a fresh handle rather than reusing a freed one — see resource cleanup.

#Next