BabylonJS/Babylon.js · error
Decorator metadata is unavailable; the Symbol.metadata (${St
Error message
Decorator metadata is unavailable; the Symbol.metadata (${String(MetadataSymbol)}) polyfill must run before decorated classes are evaluated. What it means
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.
Source
Thrown at packages/dev/core/src/Misc/decorators.functions.ts:93
writable: true,
enumerable: false,
});
}
return ctor[MetadataSymbol];
}
/**
* Returns (creating if necessary) the serialization store owned by the provided decorator metadata.
* Used by the TC39 decorators, which receive `context.metadata` directly.
* @internal
*/
export function GetDirectStoreFromMetadata(metadata: DecoratorMetadataObject): SerializedPropertyMetadataMap {
if (!metadata) {
// `metadata` is `context.metadata`, which is `void 0` when `Symbol.metadata` was not installed
// before the class was evaluated. Referencing `MetadataSymbol` here (a) produces an actionable
// error instead of a cryptic "Cannot convert undefined to object" and (b) keeps the module-load
// polyfill anchored so bundlers cannot tree-shake it away on the decorate-time serialize path.
throw new Error(`Decorator metadata is unavailable; the Symbol.metadata (${String(MetadataSymbol)}) polyfill must run before decorated classes are evaluated.`);
}
if (!HasOwn(metadata, __bjsSerializableKey)) {
(metadata as any)[__bjsSerializableKey] = {};
}
return (metadata as any)[__bjsSerializableKey];
}
/** @internal */
export function GetDirectStore(target: any): SerializedPropertyMetadataMap {
const metadata = GetOwnMetadata(GetConstructor(target));
if (!metadata) {
return {};
}
if (!HasOwn(metadata, __bjsSerializableKey)) {
metadata[__bjsSerializableKey] = {};
}
return metadata[__bjsSerializableKey];
}View on GitHub (pinned to 0592b347b8)
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
Example fix
// before
import { serializable } from 'core/Misc/decorators';
@serializable()
class Foo {}
// after
import 'core/Misc/decorators.metadata'; // polyfill, must run first
import { serializable } from 'core/Misc/decorators';
@serializable()
class Foo {} Defensive patterns
Strategy: validation
Validate before calling
if (typeof (Symbol as any).metadata !== 'symbol') {
throw new Error('Symbol.metadata unavailable: import the decorators metadata polyfill before decorated classes');
} Try / catch
try {
serialize(obj);
} catch (e) {
if (e instanceof Error && e.message.includes('Decorator metadata is unavailable')) {
console.error('Add `import "core/Misc/decorators.metadata"` as the first import in your entry point', e);
} else {
throw e;
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- EditableInPropertyPage: decorator metadata is unavailable; t
- Unknown vector class name ${className}
- GaussianSplattingPartProxyMesh: compound mesh not found with
- TrailMesh: generator not found with ID
- Method not implemented.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/3b3280209cd6bcff.
Report an issue: GitHub.