BabylonJS/Babylon.js · error · Error

Not a valid binary FBX file

Error message

Not a valid binary FBX file

What it means

parseBinaryFBX validates the file begins with the exact 21-byte magic string `Kaydara FBX Binary \0`. If the first bytes differ, the input is not a binary FBX file, and parsing cannot proceed — the parser throws immediately before reading the header/version.

Source

Thrown at packages/dev/loaders/src/FBX/parsers/fbxBinaryParser.ts:19

/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */
import { type FBXDocument, type FBXNode, type FBXProperty, type FBXPropertyType } from "../types/fbxTypes";
import { inflateZlib } from "./zlibInflate";

const FBX_MAGIC = "Kaydara FBX Binary  \0";
const HEADER_SIZE = 27; // 21 magic + 2 padding + 4 version uint32

/**
 * Parse a binary FBX file into an FBXDocument.
 * Supports FBX versions 7.0–7.7 (v7.5+ uses 64-bit node headers).
 */
export function parseBinaryFBX(buffer: ArrayBuffer): FBXDocument {
    const view = new DataView(buffer);
    const bytes = new Uint8Array(buffer);

    // Validate magic
    const magic = decodeASCII(bytes, 0, 21);
    if (magic !== FBX_MAGIC) {
        throw new Error("Not a valid binary FBX file");
    }
    if (buffer.byteLength < HEADER_SIZE) {
        throw new Error("Truncated binary FBX header");
    }

    const version = view.getUint32(23, true);
    // v7.5+ uses 64-bit offsets in node records
    const is64Bit = version >= 7500;

    const nodes: FBXNode[] = [];
    let offset = HEADER_SIZE;

    while (offset < buffer.byteLength) {
        const result = parseNode(view, bytes, offset, is64Bit, buffer.byteLength);
        if (result === null) {
            break; // null sentinel node
        }
        nodes.push(result.node);

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Check the first bytes of the file — if it starts with `Kaydara FBX Binary` it is binary; if it starts with text like `; FBX` use the ASCII parser
  2. If the file starts with `PK`, it is a ZIP — unzip it to get the real FBX
  3. Re-export the asset as FBX binary from the DCC tool
  4. Verify the file was not truncated/transformed in transit (e.g. text-mode transfer corrupting bytes)

Example fix

// before
loader.parse(fbxBytes); // bytes are actually ASCII FBX
// after
const isBinary = new TextDecoder().decode(bytes.slice(0, 21)) === "Kaydara FBX Binary  ";
if (isBinary) loader.parse(bytes); else loader.parse(text);
Defensive patterns

Strategy: validation

Validate before calling

const MAGIC = "Kaydara FBX Binary  \0";
function isBinaryFbx(buf) {
  if (buf.byteLength < 27) return false;
  let s = "";
  const b = new Uint8Array(buf, 0, 21);
  for (const x of b) s += String.fromCharCode(x);
  return s === MAGIC;
}
if (!isBinaryFbx(buffer)) throw new Error("Not binary FBX — use the ASCII parser or convert the file");

Type guard

function isBinaryFbxBuffer(buf) {
  if (!(buf instanceof ArrayBuffer) || buf.byteLength < 27) return false;
  const magic = String.fromCharCode(...new Uint8Array(buf, 0, 21));
  return magic === "Kaydara FBX Binary  \0";
}

Try / catch

try {
  const doc = parseBinaryFBX(buffer);
} catch (e) {
  if (e.message === "Not a valid binary FBX file") {
    // sniff: PK => zip, '<' or '; FBX' => ascii/xml; route accordingly
    console.error("Wrong format fed to binary FBX parser");
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the loader's ArrayBuffer parse path (via `_parseFromArrayBuffer`/`doc`) with bytes that are ASCII FBX, a ZIP archive (often mistakenly called .fbx), an OBJ/DAE file, or any non-FBX binary.

Common situations: Feeding ASCII FBX into the binary parser (or vice versa); renaming a .zip (FBX 2020+ default is actually binary but some pipelines store zipped FBX) or .dae to .fbx; corrupted uploads where the magic bytes are lost.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/1b69fb60d2ef8726. Report an issue: GitHub.