mastra-ai/mastra · error · HTTPException

metadata.avatarUrl exceeds ${AVATAR_MAX_BYTES}-byte limit (g

Error message

metadata.avatarUrl exceeds ${AVATAR_MAX_BYTES}-byte limit (got ${byteLength})

What it means

HTTP 413 (Payload Too Large) from validateMetadataAvatarUrl: the decoded avatar exceeds AVATAR_MAX_BYTES. The message reports the limit and the actual decoded byte length, so callers can size their payload accordingly.

Source

Thrown at packages/server/src/server/handlers/validate-avatar.ts:43

  // `Buffer.from(..., 'base64')` decodes leniently — it silently ignores
  // invalid characters and never throws. Validate the payload format strictly
  // before measuring its byte length so malformed input is rejected.
  const base64Payload = match[2]!;
  const isStrictBase64 =
    base64Payload.length > 0 &&
    base64Payload.length % 4 === 0 &&
    /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(base64Payload);
  if (!isStrictBase64) {
    throw new HTTPException(400, { message: 'metadata.avatarUrl contains invalid base64' });
  }
  const byteLength = Buffer.from(base64Payload, 'base64').byteLength;

  if (byteLength === 0) {
    throw new HTTPException(400, { message: 'metadata.avatarUrl is empty' });
  }

  if (byteLength > AVATAR_MAX_BYTES) {
    throw new HTTPException(413, {
      message: `metadata.avatarUrl exceeds ${AVATAR_MAX_BYTES}-byte limit (got ${byteLength})`,
    });
  }
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Resize/compress the image client-side (e.g. canvas resize, JPEG quality ~0.8) until under AVATAR_MAX_BYTES decoded bytes.
  2. Check the decoded size before submitting: Buffer.from(base64Payload, 'base64').byteLength.
  3. Host large images externally and reference them via a non-avatarUrl metadata key if supported.

Example fix

// before
const avatarUrl = 'data:image/png;base64,' + originalPhotoBase64; // decodes to ~4MB
// after
const small = await resizeToDataUrl(file, { maxWidth: 256, mime: 'image/jpeg', quality: 0.8 });
metadata: { avatarUrl: small }
Defensive patterns

Strategy: validation

Validate before calling

const AVATAR_MAX_BYTES = 200 * 1024; // check your server's limit
const bytes = Buffer.from((metadata.avatarUrl ?? '').split(',')[1] ?? '', 'base64').byteLength;
if (bytes > AVATAR_MAX_BYTES) {
  metadata.avatarUrl = await downscaleToDataUrl(metadata.rawAvatar, AVATAR_MAX_BYTES);
}

Try / catch

try {
  await saveAgent({ metadata });
} catch (e) {
  if (e instanceof HTTPException && e.status === 413) {
    const limit = parseLimitFromMessage(e.message);
    metadata.avatarUrl = await downscaleToDataUrl(metadata.rawAvatar, limit);
    await saveAgent({ metadata });
  } else throw e;
}

Prevention

When it happens

Trigger: POST/PUT to agent create/update routes with a base64 avatar whose decoded size exceeds AVATAR_MAX_BYTES (e.g. uploading multi-MB photos).

Common situations: Users picking high-resolution photos as avatars from an unresized file input; PNG screenshots instead of compressed JPEGs; forgetting base64 inflates size ~33% over raw bytes.

Related errors


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