BabylonJS/Babylon.js · error

EditableInPropertyPage: decorator metadata is unavailable; t

Error message

EditableInPropertyPage: decorator metadata is unavailable; the Symbol.metadata (${String(MetadataSymbol)}) polyfill must run before decorated classes are evaluated.

What it means

The EditableInPropertyPage decorator (Stage decorator API) stores property-editing metadata on context.metadata, which is only populated when Symbol.metadata is installed (native or via the MetadataSymbol polyfill from core). If a decorated class is evaluated before the polyfill runs, context.metadata is undefined and this error is thrown. It is deliberately a hard failure so decorated classes are never silently stripped of editor metadata.

Source

Thrown at packages/dev/smartFilters/src/editorUtils/editableInPropertyPage.ts:107

 * @param propertyType - the type of the property
 * @param groupName - the group name of the property
 * @param options - the options of the property
 * @returns the decorator
 */
export function EditableInPropertyPage(
    displayName: string,
    propertyType: PropertyTypeForEdition = PropertyTypeForEdition.Boolean,
    groupName: string = "PROPERTIES",
    options?: IEditablePropertyOption
) {
    return (_value: unknown, context: { name: string | symbol; metadata: DecoratorMetadataObject }) => {
        const meta = context.metadata as DecoratorMetadataObject | undefined;
        if (!meta) {
            // `context.metadata` is `void 0` when `Symbol.metadata` was not installed before this class
            // was evaluated. Importing `MetadataSymbol` from core runs the polyfill at module load (before
            // this class body), so this should never happen; referencing it here also keeps that
            // module-load polyfill anchored against bundler tree-shaking.
            throw new Error(
                `EditableInPropertyPage: decorator metadata is unavailable; the Symbol.metadata (${String(MetadataSymbol)}) polyfill must run before decorated classes are evaluated.`
            );
        }
        let propStore: IPropertyDescriptionForEdition[];
        if (Object.prototype.hasOwnProperty.call(meta, __bjsSmartFilterPropStoreKey)) {
            propStore = meta[__bjsSmartFilterPropStoreKey] as IPropertyDescriptionForEdition[];
        } else {
            propStore = [];
            meta[__bjsSmartFilterPropStoreKey] = propStore;
        }

        const propertyKey = String(context.name);

        const propToAdd: IPropertyDescriptionForEdition = {
            propertyName: propertyKey,
            displayName: displayName,
            type: propertyType,
            groupName: groupName,

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Import MetadataSymbol from core at the very top of your entry point (e.g. import 'core/Misc/decorator.metadata' equivalent) so the polyfill runs before any decorated class loads.
  2. Keep the polyfill import side-effectful (do not rely on named bindings bundlers may tree-shake).
  3. Fix import cycles so the polyfill module is not loaded after decorated class modules.
  4. Use a JS runtime/engine version that supports native Symbol.metadata.

Example fix

// before
import { EditableInPropertyPage } from "@babylonjs/smartFilters/Editor/editableInPropertyPage";
import { MyBlock } from "./myBlock";
// after
import { MetadataSymbol } from "@babylonjs/core/Misc/metadata.symbol"; // polyfill side-effect first
import { EditableInPropertyPage } from "@babylonjs/smartFilters/Editor/editableInPropertyPage";
import { MyBlock } from "./myBlock";
Defensive patterns

Strategy: validation

Validate before calling

if (typeof Symbol.metadata === "undefined") {
  // polyfill not installed yet
  throw new Error("Import MetadataSymbol from core before importing decorated classes");
}

Type guard

null

Try / catch

try {
  const mod = await import("./blocks/decoratedBlocks");
} catch (e) {
  if (String(e).includes("decorator metadata is unavailable")) {
    console.error("Ensure the Symbol.metadata polyfill import precedes decorated class imports");
  } else throw e;
}

Prevention

When it happens

Trigger: Importing a module containing @editableInPropertyPage-decorated classes without first importing MetadataSymbol from core; bundler tree-shaking removing the polyfill import; circular imports where the decorated class module loads before the polyfill module.

Common situations: Reordering imports after a refactor; a bundler (Vite/Rollup/webpack) dropping a side-effect-only import it considers unused; migrating Babylon.js versions where the Symbol.metadata polyfill was introduced.

Related errors


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