dotnet/AspNetCore.Docs · error · Error
When calling ko.mapping.toJS, pass the object you want to co
Error message
When calling ko.mapping.toJS, pass the object you want to convert.
What it means
knockout.mapping's toJS unwraps an observable view model back to plain JS. Like fromJS, it guards on zero arguments — without a root object there is nothing to unwrap, so it throws rather than return undefined. This is the symmetric counterpart to the fromJS argument check.
Source
Thrown at aspnetcore/mvc/controllers/testing/samples/2.x/TestingControllersSample/src/TestingControllersSample/wwwroot/js/knockout.mapping.js:154
exports.fromJSON = function (jsonString /*, options, target*/ ) {
var parsed = ko.utils.parseJson(jsonString);
arguments[0] = parsed;
return exports.fromJS.apply(this, arguments);
};
exports.updateFromJS = function (viewModel) {
throw new Error("ko.mapping.updateFromJS, use ko.mapping.fromJS instead. Please note that the order of parameters is different!");
};
exports.updateFromJSON = function (viewModel) {
throw new Error("ko.mapping.updateFromJSON, use ko.mapping.fromJSON instead. Please note that the order of parameters is different!");
};
exports.toJS = function (rootObject, options) {
if (!defaultOptions) exports.resetDefaultOptions();
if (arguments.length == 0) throw new Error("When calling ko.mapping.toJS, pass the object you want to convert.");
if (exports.getType(defaultOptions.ignore) !== "array") throw new Error("ko.mapping.defaultOptions().ignore should be an array.");
if (exports.getType(defaultOptions.include) !== "array") throw new Error("ko.mapping.defaultOptions().include should be an array.");
if (exports.getType(defaultOptions.copy) !== "array") throw new Error("ko.mapping.defaultOptions().copy should be an array.");
// Merge in the options used in fromJS
options = fillOptions(options, rootObject[mappingProperty]);
// We just unwrap everything at every level in the object graph
return exports.visitModel(rootObject, function (x) {
return ko.utils.unwrapObservable(x)
}, options);
};
exports.toJSON = function (rootObject, options) {
var plainJavaScriptObject = exports.toJS(rootObject, options);
return ko.utils.stringifyJson(plainJavaScriptObject);
};
View on GitHub (pinned to c67a80103a)
Solutions
- Pass the root object: ko.mapping.toJS(viewModel).
- Guard the caller: if (viewModel) ko.mapping.toJS(viewModel);
- Provide a fallback: ko.mapping.toJS(viewModel || {}).
Example fix
// before
const plain = ko.mapping.toJS(); // throws
// after
const plain = ko.mapping.toJS(viewModel || {}); Defensive patterns
Strategy: validation
Validate before calling
// Guard toJS against a missing root object.
function safeToJS(rootObject, options) {
if (rootObject == null) {
console.warn('ko.mapping.toJS called with no root; returning {}');
return {};
}
return ko.mapping.toJS(rootObject, options);
} Type guard
function isUnwrappable(x) { return x != null && (ko.isObservable(x) || typeof x === 'object'); } Try / catch
try {
return ko.mapping.toJS(viewModel);
} catch (e) {
if (/pass the object you want to convert/.test(e.message)) {
console.error('toJS called with no argument');
return {};
}
throw e;
} Prevention
- Coalesce: ko.mapping.toJS(viewModel || {}).
- Null-check view models after async teardown before unwrapping.
- Centralize serialization in one helper that validates the root.
When it happens
Trigger: Calling ko.mapping.toJS() with no arguments; calling it after a variable that turned out to be undefined.
Common situations: Posting data back to server but the view-model reference was nulled; refactor that dropped the parameter; conditional flow.
Related errors
- When calling ko.fromJS, pass the object you want to convert.
- When calling ko.fromJS, pass the object you want to convert.
- ko.mapping.defaultOptions().ignore should be an array.
- ko.mapping.defaultOptions().include should be an array.
- ko.mapping.updateFromJS, use ko.mapping.fromJS instead. Plea
AI-assisted analysis of dotnet/AspNetCore.Docs@c67a80103a (2026-08-13).
Data as JSON: /api/errors/fd5040db9912cd0e.
Report an issue: GitHub.