SignalR/SignalR · error · Error

The binding ' + bindingName + ' cannot be used with virtual

Error message

The binding ' + bindingName + ' cannot be used with virtual elements

What it means

validateThatBindingIsAllowedForVirtualElements checks ko.virtualElements.allowedBindings for the binding name. If the binding is not registered there, it throws, because not all bindings can work with virtual (comment-based) elements — only those explicitly whitelisted. This prevents bindings that require a real DOM element from being applied to a comment node.

Source

Thrown at samples/Microsoft.AspNet.SignalR.LoadTestHarness/Scripts/knockout-2.1.0.debug.js:1891

            this['$parents'].unshift(this['$parent']);
        } else {
            this['$parents'] = [];
            this['$root'] = dataItem;
        }
        this['$data'] = dataItem;
    }
    ko.bindingContext.prototype['createChildContext'] = function (dataItem) {
        return new ko.bindingContext(dataItem, this);
    };
    ko.bindingContext.prototype['extend'] = function(properties) {
        var clone = ko.utils.extend(new ko.bindingContext(), this);
        return ko.utils.extend(clone, properties);
    };

    function validateThatBindingIsAllowedForVirtualElements(bindingName) {
        var validator = ko.virtualElements.allowedBindings[bindingName];
        if (!validator)
            throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
    }

    function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
        var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
        while (currentChild = nextInQueue) {
            // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
            nextInQueue = ko.virtualElements.nextSibling(currentChild);
            applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
        }
    }

    function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
        var shouldBindDescendants = true;

        // Perf optimisation: Apply bindings only if...
        // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
        //     Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
        // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)

View on GitHub (pinned to 693053b89a)

Solutions

  1. Move the binding to a real DOM element instead of using containerless comment syntax.
  2. If using a custom binding handler with virtual elements, register it: ko.virtualElements.allowedBindings['myBinding'] = true.
  3. Only use containerless bindings for flow-control bindings explicitly designed for virtual elements.

Example fix

<!-- before: 'value' not allowed in virtual element -->
<!-- ko value: someProperty --><!-- /ko -->
<!-- after: use a real input element -->
<input data-bind='value: someProperty' />
Defensive patterns

Strategy: validation

Validate before calling

// Check if a binding is allowed for virtual elements
function isAllowedForVirtualElements(bindingName) {
    return !!ko.virtualElements.allowedBindings[bindingName];
}

// Known allowed bindings in KO 2.1.0: if, ifnot, foreach, with, template
// Before using a binding in containerless syntax:
if (!isAllowedForVirtualElements('myCustomBinding')) {
    console.warn('myCustomBinding cannot be used with <!-- ko --> virtual elements');
}

Try / catch

try {
    ko.applyBindings(viewModel, element);
} catch (e) {
    if (e.message.indexOf('cannot be used with virtual elements') !== -1) {
        console.error('This binding requires a real DOM element, not a virtual element:', e.message);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Using a binding inside a virtual element (<!-- ko bindingName: ... -->) where bindingName is not registered in ko.virtualElements.allowedBindings. For example, using 'value' or 'checked' in a containerless binding, as these require a real form element. Only bindings like 'if', 'foreach', 'with', 'template' are typically whitelisted.

Common situations: A developer wraps a binding that needs a real element (like 'value', 'attr', 'css') in containerless comment syntax. Using a custom binding handler in a virtual element without registering it in ko.virtualElements.allowedBindings.

Related errors


AI-assisted analysis of SignalR/SignalR@693053b89a (2026-08-13). Data as JSON: /api/errors/91621728fe81fe1b. Report an issue: GitHub.