BabylonJS/Babylon.js · error

ProjectFile: Invalid project file — 'companionBindings' must

Error message

ProjectFile: Invalid project file — 'companionBindings' must be an object.

What it means

The optional 'companionBindings' property, when present, must be a plain object (not null, not an array). DeserializeProject performs a shape-only check and rejects documents where this property has any other type.

Source

Thrown at packages/dev/sharedUiComponents/src/projects/projectFile.ts:306

    const doc = data as Record<string, unknown>;

    if (doc.version !== 2) {
        throw new Error(`ProjectFile: Unsupported project version "${doc.version}". Expected version 2.`);
    }

    // Validate the asset map portion
    DeserializeSmartAssetMap({ version: 1, assets: doc.assets });

    // Validate overrides array
    if (!Array.isArray(doc.overrides)) {
        throw new Error("ProjectFile: Invalid project file — 'overrides' must be an array.");
    }

    // Validate optional companion bindings (shape-only check)
    if (doc.companionBindings !== undefined) {
        if (typeof doc.companionBindings !== "object" || doc.companionBindings === null || Array.isArray(doc.companionBindings)) {
            throw new Error("ProjectFile: Invalid project file — 'companionBindings' must be an object.");
        }
    }

    return data as ISerializedProject;
}

// ── Zip layer (.babylonproj on disk) ──

/**
 * Serializes a scene's project (smart assets + overrides) into a `.babylonproj`
 * zip bundle.
 *
 * The zip contains:
 * - `project.json` — the project document (assets + overrides)
 * - `__project_locals__.babylon` — companion file for user-created objects (if any)
 * - Bundled local asset files (blobs the user dragged in from disk)
 *
 * Remote URLs (http/https) are left as references and not bundled.

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Change companionBindings to a plain object keyed by binding id/name.
  2. Omit the property entirely (or use undefined) if there are no companion bindings.
  3. Round-trip the project through the official save path to regenerate the correct shape.
  4. Add a pre-parse check: typeof doc.companionBindings === 'object' && !Array.isArray(doc.companionBindings).

Example fix

// before
{ "version": 2, "overrides": [], "companionBindings": [ {"id":"a"} ] }
// after
{ "version": 2, "overrides": [], "companionBindings": { "a": { } } }
Defensive patterns

Strategy: type-guard

Validate before calling

if (doc.companionBindings !== undefined &&
    (typeof doc.companionBindings !== 'object' || doc.companionBindings === null || Array.isArray(doc.companionBindings))) {
    throw new Error('companionBindings must be a plain object');
}

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> {
    return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try {
    DeserializeProject(doc);
} catch (e) {
    if (e instanceof Error && e.message.includes("'companionBindings' must be an object")) {
        delete doc.companionBindings;
        return DeserializeProject(doc);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling DeserializeProject where doc.companionBindings is a string, number, boolean, null, or an array (typeof 'object' but Array.isArray true).

Common situations: Hand-editing companion bindings, a serialization tool emitting an array of bindings instead of a keyed object, or copying an example with the wrong shape.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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