mastra-ai/mastra · error · Error

fourcc must be 4 ASCII characters, got "${s}"

Error message

fourcc must be 4 ASCII characters, got "${s}"

What it means

The MJPEG-AVI encoder validates every FourCC chunk/RIFF tag before encoding. FourCC codes are by definition exactly 4 ASCII bytes; anything else would corrupt the AVI container structure, so the helper fourcc() throws if the string length is not 4. In practice this fires when internal tag constants are edited or when custom tags are passed incorrectly.

Source

Thrown at packages/core/src/browser/recording/mjpeg-avi.ts:59

const FOURCC_MJPG = fourcc('MJPG');
const FOURCC_MOVI = fourcc('movi');
const FOURCC_IDX1 = fourcc('idx1');
const FOURCC_00DC = fourcc('00dc');

const AVIF_HASINDEX = 0x00000010;
const AVIIF_KEYFRAME = 0x00000010;

const AVIH_SIZE = 56;
const STRH_SIZE = 56;
const STRF_SIZE = 40; // BITMAPINFOHEADER, no extra data
const LIST_TYPE_SIZE = 4; // 4 bytes for the LIST type ("hdrl", "movi", etc.)
const CHUNK_HEADER_SIZE = 8; // fourcc (4) + size (4)
const MAX_U32 = 0xffffffff;
const MAX_I16 = 0x7fff;

function fourcc(s: string): Buffer {
  if (s.length !== 4) {
    throw new Error(`fourcc must be 4 ASCII characters, got "${s}"`);
  }
  return Buffer.from(s, 'ascii');
}

/**
 * Encode a list of MJPEG frames as an AVI 1.0 file.
 *
 * The file is written incrementally to disk so we don't have to hold the whole
 * AVI in memory — large recordings can be hundreds of MB.
 */
export function writeMjpegAviFile(filePath: string, frames: readonly MjpegFrame[], opts: MjpegAviOptions): void {
  if (frames.length === 0) {
    throw new Error('writeMjpegAviFile: at least one frame is required');
  }
  if (opts.width <= 0 || opts.height <= 0 || !Number.isInteger(opts.width) || !Number.isInteger(opts.height)) {
    throw new Error(`writeMjpegAviFile: invalid dimensions ${opts.width}x${opts.height}`);
  }
  if (opts.width > MAX_I16 || opts.height > MAX_I16) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Correct the tag constant to exactly 4 ASCII characters ('RIFF', 'AVI ', 'LIST', 'hdrl', 'avih', 'strl', ...).
  2. Pad short tags with spaces (AVI convention) rather than shorter strings.
  3. Add a unit test covering every tag constant passed to fourcc().
  4. Check string length at construction time with a compile-time const assertion if extending.

Example fix

// before
const FOURCC_AVIH = 'AVIHDR'; // 6 chars -> throws
// after
const FOURCC_AVIH = 'avih'; // exactly 4 ASCII chars
Defensive patterns

Strategy: validation

Validate before calling

function assertFourcc(s: string): asserts s is Fourcc {
  if (s.length !== 4) throw new Error(`invalid fourcc: ${JSON.stringify(s)}`);
}
assertFourcc(customTag);

Type guard

type Fourcc = string & { __brand: 'fourcc' };
function isFourcc(s: string): s is Fourcc {
  return s.length === 4 && /^[\x20-\x7e]{4}$/.test(s);
}

Try / catch

try {
  const avi = encodeMjpegAvi(frames, { tags: { avih: customAvihTag } });
} catch (err) {
  if (err instanceof Error && err.message.startsWith('fourcc must be 4 ASCII characters')) {
    console.error('Bad tag constant:', err.message); // fix the constant, do not retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing a string whose length != 4 to fourcc() (directly or via a custom tag constant) — e.g. 'AVII', 'RIFFS', an empty string, or a variable holding a truncated/concatenated tag.

Common situations: Extending the encoder with custom chunk types and mistyping the tag; refactoring constants with accidental whitespace or concatenation; localization/encoding mishaps turning a 4-char tag into a multibyte sequence of different JS length.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/ec3b18c492a12daf. Report an issue: GitHub.