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

  1. Pass the root object: ko.mapping.toJS(viewModel).
  2. Guard the caller: if (viewModel) ko.mapping.toJS(viewModel);
  3. 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

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


AI-assisted analysis of dotnet/AspNetCore.Docs@c67a80103a (2026-08-13). Data as JSON: /api/errors/fd5040db9912cd0e. Report an issue: GitHub.