SignalR/SignalR · error · Error
When calling ko.toJS, pass the object you want to convert.
Error message
When calling ko.toJS, pass the object you want to convert.
What it means
ko.toJS recursively unwraps observables in an object graph to produce a plain JavaScript object. It requires at least one argument — the root object to convert. If called with zero arguments (arguments.length === 0), it throws immediately. This prevents undefined behavior from processing an undefined root.
Source
Thrown at samples/Microsoft.AspNet.SignalR.LoadTestHarness/Scripts/knockout-2.1.0.debug.js:1275
return ko.hasPrototype(instance, ko.dependentObservable);
};
var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
ko.dependentObservable[protoProp] = ko.observable;
ko.dependentObservable['fn'] = {};
ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
ko.exportSymbol('dependentObservable', ko.dependentObservable);
ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
ko.exportSymbol('isComputed', ko.isComputed);
(function() {
var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
ko.toJS = function(rootObject) {
if (arguments.length == 0)
throw new Error("When calling ko.toJS, pass the object you want to convert.");
// We just unwrap everything at every level in the object graph
return mapJsObjectGraph(rootObject, function(valueToMap) {
// Loop because an observable's value might in turn be another observable wrapper
for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
valueToMap = valueToMap();
return valueToMap;
});
};
ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
var plainJavaScriptObject = ko.toJS(rootObject);
return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
};
function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
visitedObjects = visitedObjects || new objectLookup();
View on GitHub (pinned to 693053b89a)
Solutions
- Ensure the root object argument is passed and is defined before calling ko.toJS.
- Add a default or guard: ko.toJS(rootObject || {}).
Example fix
// before — argument may be undefined
var plain = ko.toJS(maybeUndefined);
// after — provide a default
var plain = ko.toJS(maybeUndefined || {}); Defensive patterns
Strategy: validation
Validate before calling
// Always pass a root object to ko.toJS
function safeToJS(rootObject) {
if (arguments.length === 0 || rootObject === undefined) {
console.warn('ko.toJS called without a root object');
return null;
}
return ko.toJS(rootObject);
} Type guard
function isDefined(val) {
return val !== undefined && val !== null;
} Prevention
- Always pass an explicit root object to ko.toJS() and ko.toJSON().
- Use a default value when the source is optional: ko.toJS(rootObject || {}).
- Add parameter validation in helper functions that wrap ko.toJS.
When it happens
Trigger: Calling ko.toJS() with no arguments. Calling ko.toJSON() with no arguments (which internally calls ko.toJS). A variable that was expected to hold the root object is undefined when passed.
Common situations: A function that conditionally calls ko.toJS but the argument is undefined in some code paths. A serialization helper that passes an optional parameter without a default.
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/51a4c7612bac6c7b.
Report an issue: GitHub.