BabylonJS/Babylon.js · error

Aggregate blocks should not be prepared for runtime.

Error message

Aggregate blocks should not be prepared for runtime.

What it means

AggregateBlock represents a sub-graph of blocks and has no standalone runtime representation. prepareForRuntime is intentionally overridden to always throw, because merging the internal graph happens through the aggregate-specific mechanism instead.

Source

Thrown at packages/dev/smartFilters/src/blockFoundation/aggregateBlock.ts:35

     * The class name of the block.
     */
    public static override ClassName = "AggregateBlock";

    /**
     * The list of relationships between the internal graph output and the outside ones.
     */
    private readonly _aggregatedOutputs: [ConnectionPoint, ConnectionPoint][] = [];

    /**
     * The list of relationships between the internal graph inputs and the outside ones.
     */
    private readonly _aggregatedInputs: [ConnectionPoint[], ConnectionPoint][] = [];

    /**
     * Do not override prepareForRuntime for aggregate blocks. It is not supported.
     */
    public override prepareForRuntime(): never {
        throw new Error("Aggregate blocks should not be prepared for runtime.");
    }

    /**
     * @internal
     * Merges the internal graph into the SmartFilter
     */
    public _mergeIntoSmartFilter(mergedAggregateBlocks: AggregateBlock[]): void {
        // Rewire output connections
        for (const [internalConnectionPoint, externalConnectionPoint] of this._aggregatedOutputs) {
            const endpointsToConnectTo = externalConnectionPoint.endpoints.slice();
            externalConnectionPoint.disconnectAllEndpoints();
            for (const endpoint of endpointsToConnectTo) {
                internalConnectionPoint.connectTo(endpoint);
            }
        }

        // Rewire input connections
        for (const [internalConnectionPoints, externalConnectionPoint] of this._aggregatedInputs) {

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Skip aggregate blocks in your loop: only call prepareForRuntime on non-aggregate blocks (check via getClassName or instanceof).
  2. Let the SmartFilter runtime merge aggregate sub-filters automatically via the internal merge path instead of preparing them manually.
  3. If you wrote a custom aggregate block, do not override prepareForRuntime; extend the aggregate registration API instead.

Example fix

// before
for (const block of filter.blocks) block.prepareForRuntime();
// after
for (const block of filter.blocks) {
    if (!(block instanceof AggregateBlock)) block.prepareForRuntime();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (block instanceof AggregateBlock) {
    // skip — aggregate blocks merge via the internal graph, not prepareForRuntime
} else {
    block.prepareForRuntime();
}

Type guard

function isNotAggregate(block: BaseBlock): block is Exclude<BaseBlock, AggregateBlock> {
    return !(block instanceof AggregateBlock);
}

Try / catch

try {
    block.prepareForRuntime();
} catch (e) {
    if (e instanceof Error && e.message.includes('Aggregate blocks should not be prepared')) {
        // ignore: aggregates are merged by the SmartFilter runtime
    } else throw e;
}

Prevention

When it happens

Trigger: Calling prepareForRuntime() directly on any block whose class extends AggregateBlock (e.g. CustomAggregateBlock), or calling it generically over all blocks in a filter without skipping aggregates.

Common situations: Iterating filter.blocks and calling prepareForRuntime on each; custom block subclasses incorrectly overriding prepareForRuntime on an aggregate; framework code that assumes every block is runtime-preparable.

Related errors


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