{"record":{"id":"0398a3ee034f9a33","repo":"BabylonJS/Babylon.js","slug":"projectfile-invalid-project-file-companionbind","errorCode":null,"errorMessage":"ProjectFile: Invalid project file — 'companionBindings' must be an object.","messagePattern":"ProjectFile: Invalid project file — 'companionBindings' must be an object\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/sharedUiComponents/src/projects/projectFile.ts","lineNumber":306,"sourceCode":"\r\n    const doc = data as Record<string, unknown>;\r\n\r\n    if (doc.version !== 2) {\r\n        throw new Error(`ProjectFile: Unsupported project version \"${doc.version}\". Expected version 2.`);\r\n    }\r\n\r\n    // Validate the asset map portion\r\n    DeserializeSmartAssetMap({ version: 1, assets: doc.assets });\r\n\r\n    // Validate overrides array\r\n    if (!Array.isArray(doc.overrides)) {\r\n        throw new Error(\"ProjectFile: Invalid project file — 'overrides' must be an array.\");\r\n    }\r\n\r\n    // Validate optional companion bindings (shape-only check)\r\n    if (doc.companionBindings !== undefined) {\r\n        if (typeof doc.companionBindings !== \"object\" || doc.companionBindings === null || Array.isArray(doc.companionBindings)) {\r\n            throw new Error(\"ProjectFile: Invalid project file — 'companionBindings' must be an object.\");\r\n        }\r\n    }\r\n\r\n    return data as ISerializedProject;\r\n}\r\n\r\n// ── Zip layer (.babylonproj on disk) ──\r\n\r\n/**\r\n * Serializes a scene's project (smart assets + overrides) into a `.babylonproj`\r\n * zip bundle.\r\n *\r\n * The zip contains:\r\n * - `project.json` — the project document (assets + overrides)\r\n * - `__project_locals__.babylon` — companion file for user-created objects (if any)\r\n * - Bundled local asset files (blobs the user dragged in from disk)\r\n *\r\n * Remote URLs (http/https) are left as references and not bundled.\r","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/sharedUiComponents/src/projects/projectFile.ts#L288-L324","documentation":"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.","triggerScenarios":"Calling DeserializeProject where doc.companionBindings is a string, number, boolean, null, or an array (typeof 'object' but Array.isArray true).","commonSituations":"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.","solutions":["Change companionBindings to a plain object keyed by binding id/name.","Omit the property entirely (or use undefined) if there are no companion bindings.","Round-trip the project through the official save path to regenerate the correct shape.","Add a pre-parse check: typeof doc.companionBindings === 'object' && !Array.isArray(doc.companionBindings)."],"exampleFix":"// before\n{ \"version\": 2, \"overrides\": [], \"companionBindings\": [ {\"id\":\"a\"} ] }\n// after\n{ \"version\": 2, \"overrides\": [], \"companionBindings\": { \"a\": { } } }","handlingStrategy":"type-guard","validationCode":"if (doc.companionBindings !== undefined &&\n    (typeof doc.companionBindings !== 'object' || doc.companionBindings === null || Array.isArray(doc.companionBindings))) {\n    throw new Error('companionBindings must be a plain object');\n}","typeGuard":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n    return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n    DeserializeProject(doc);\n} catch (e) {\n    if (e instanceof Error && e.message.includes(\"'companionBindings' must be an object\")) {\n        delete doc.companionBindings;\n        return DeserializeProject(doc);\n    }\n    throw e;\n}","preventionTips":["Model companionBindings as a keyed record type in your editor code, not an array.","Round-trip projects through the official serializer after manual edits.","Use isPlainObject as a pre-check on every optional map-shaped field."],"tags":["deserialization","validation","json"],"backgroundTag":"schema-validation-failed","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}