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.js guards `toJS` by checking `arguments.length == 0` and throws when no rootObject is passed. toJS recursively unwraps observables, so it has nothing to operate on without a target object.

Source

Thrown at aspnetcore/mvc/controllers/testing/samples/3.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 mapped view model: `ko.mapping.toJS(myViewModel)`.
  2. Guard the call so it only runs when the source object exists: `if (myViewModel) ko.mapping.toJS(myViewModel)`.
  3. If serializing to JSON, prefer `ko.mapping.toJSON(rootObject)` which wraps toJS.

Example fix

// before
var plain = ko.mapping.toJS();

// after
var plain = ko.mapping.toJS(myViewModel);
Defensive patterns

Strategy: validation

Validate before calling

function safeToJS(rootObject, options) {
  if (arguments.length === 0 || rootObject == null) {
    throw new TypeError('ko.mapping.toJS requires a root object');
  }
  return ko.mapping.toJS(rootObject, options);
}

Type guard

function isMappable(obj) {
  return obj != null && typeof obj === 'object';
}

Try / catch

try {
  const plain = ko.mapping.toJS(myViewModel);
} catch (e) {
  if (/pass the object/.test(e.message)) console.error('Missing rootObject for toJS');
  throw e;
}

Prevention

When it happens

Trigger: Calling `ko.mapping.toJS()` with zero arguments, or `ko.mapping.toJS(undefined)` where the argument is omitted entirely. Note: passing `undefined` explicitly still increments arguments.length in non-strict mode, so the real trigger is omitting the parameter.

Common situations: A variable intended as rootObject evaluated to nothing and the call was made unconditionally; refactored code that dropped the argument; calling toJS on a knockout object before it was assigned.

Related errors


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