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
- Move the binding to a real DOM element instead of using containerless comment syntax.
- If using a custom binding handler with virtual elements, register it: ko.virtualElements.allowedBindings['myBinding'] = true.
- 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
- Only use flow-control bindings (if, foreach, with, template) in containerless <!-- ko --> syntax.
- For custom bindings that need virtual element support, register them: ko.virtualElements.allowedBindings['myBinding'] = true.
- Move bindings that require real elements (value, checked, attr, css) to actual HTML elements.
- Review Knockout documentation for which built-in bindings support virtual elements.
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
- element must be a DOM node when calling triggerEvent
- Callback must be a function
- You can only pass a function to ko.memoization.memoize()
- Only subscribable things can act as dependencies
- The argument passed when initializing an observable array mu
AI-assisted analysis of SignalR/SignalR@693053b89a (2026-08-13).
Data as JSON: /api/errors/91621728fe81fe1b.
Report an issue: GitHub.