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

  1. Ensure the root object argument is passed and is defined before calling ko.toJS.
  2. 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

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


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