{"record":{"id":"3b3280209cd6bcff","repo":"BabylonJS/Babylon.js","slug":"decorator-metadata-is-unavailable-the-symbol-meta","errorCode":null,"errorMessage":"Decorator metadata is unavailable; the Symbol.metadata (${String(MetadataSymbol)}) polyfill must run before decorated classes are evaluated.","messagePattern":"Decorator metadata is unavailable; the Symbol\\.metadata \\((.+?)\\) polyfill must run before decorated classes are evaluated\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Misc/decorators.functions.ts","lineNumber":93,"sourceCode":"            writable: true,\n            enumerable: false,\n        });\n    }\n    return ctor[MetadataSymbol];\n}\n\n/**\n * Returns (creating if necessary) the serialization store owned by the provided decorator metadata.\n * Used by the TC39 decorators, which receive `context.metadata` directly.\n * @internal\n */\nexport function GetDirectStoreFromMetadata(metadata: DecoratorMetadataObject): SerializedPropertyMetadataMap {\n    if (!metadata) {\n        // `metadata` is `context.metadata`, which is `void 0` when `Symbol.metadata` was not installed\n        // before the class was evaluated. Referencing `MetadataSymbol` here (a) produces an actionable\n        // error instead of a cryptic \"Cannot convert undefined to object\" and (b) keeps the module-load\n        // polyfill anchored so bundlers cannot tree-shake it away on the decorate-time serialize path.\n        throw new Error(`Decorator metadata is unavailable; the Symbol.metadata (${String(MetadataSymbol)}) polyfill must run before decorated classes are evaluated.`);\n    }\n    if (!HasOwn(metadata, __bjsSerializableKey)) {\n        (metadata as any)[__bjsSerializableKey] = {};\n    }\n    return (metadata as any)[__bjsSerializableKey];\n}\n\n/** @internal */\nexport function GetDirectStore(target: any): SerializedPropertyMetadataMap {\n    const metadata = GetOwnMetadata(GetConstructor(target));\n    if (!metadata) {\n        return {};\n    }\n    if (!HasOwn(metadata, __bjsSerializableKey)) {\n        metadata[__bjsSerializableKey] = {};\n    }\n    return metadata[__bjsSerializableKey];\n}","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Misc/decorators.functions.ts#L75-L111","documentation":"Decorator metadata (Symbol.metadata) was not installed before a decorated class was evaluated, so decorator context.metadata arrives as undefined. The library throws an explicit, actionable error instead of the cryptic 'Cannot convert undefined to object' that Object.keys/HasOwn would produce, and to keep the polyfill module anchored against tree-shaking.","triggerScenarios":"Serializing a class decorated with the library's serializable decorators when the Symbol.metadata polyfill did not run at module load — typically when the decorators module is imported lazily, or a bundler tree-shook the polyfill side effect, or targeting an environment without Symbol.metadata and no polyfill import.","commonSituations":"ESBuild/rollup tree-shaking away a side-effect-only polyfill import; importing only decorator functions without the polyfill entry point; upgrading the runtime (older Node/browsers lacking Symbol.metadata) without updating setup code; split bundles where the polyfill chunk loads after the decorated class chunk.","solutions":["Import the library's metadata polyfill entry at the very top of your app entry point (before any decorated class module is imported)","Ensure the polyfill import is not tree-shaken: import it for side effects and mark it as such in bundler config (e.g. rollup sideEffects flag)","Verify the runtime supports Symbol.metadata or that the polyfill runs on all targets; check bundle chunk ordering so the polyfill executes first"],"exampleFix":"// before\nimport { serializable } from 'core/Misc/decorators';\n@serializable()\nclass Foo {}\n// after\nimport 'core/Misc/decorators.metadata'; // polyfill, must run first\nimport { serializable } from 'core/Misc/decorators';\n@serializable()\nclass Foo {}","handlingStrategy":"validation","validationCode":"if (typeof (Symbol as any).metadata !== 'symbol') {\n  throw new Error('Symbol.metadata unavailable: import the decorators metadata polyfill before decorated classes');\n}","typeGuard":null,"tryCatchPattern":"try {\n  serialize(obj);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Decorator metadata is unavailable')) {\n    console.error('Add `import \"core/Misc/decorators.metadata\"` as the first import in your entry point', e);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Import the Symbol.metadata polyfill as the first import in the app entry point","Mark the polyfill module as side-effect-only in bundler config so it is not tree-shaken","Test serialization in CI on a runtime without native Symbol.metadata to catch ordering regressions"],"tags":["decorators","symbol-metadata","polyfill","serialization"],"backgroundTag":"missing-polyfill","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}