dotnet/AspNetCore.Docs · error · Error

When calling ko.update*, the key '${key}' was not found!

Error message

When calling ko.update*, the key '${key}' was not found!

What it means

knockout.mapping's internal getItemByKey walks the array comparing mapKey(item, callback) to the requested key; if no element matches it throws. This fires during update operations when the new data references a key that isn't currently in the mapped array — typically because the client's data is stale or the key callback is inconsistent.

Source

Thrown at aspnetcore/mvc/controllers/testing/samples/2.x/TestingControllersSample/src/TestingControllersSample/wwwroot/js/knockout.mapping.js:659

		return null;
	}

	function mapKey(item, callback) {
		var mappedItem;
		if (callback) mappedItem = callback(item);
		if (exports.getType(mappedItem) === "undefined") mappedItem = item;

		return ko.utils.unwrapObservable(mappedItem);
	}

	function getItemByKey(array, key, callback) {
		array = ko.utils.unwrapObservable(array);
		for (var i = 0, j = array.length; i < j; i++) {
			var item = array[i];
			if (mapKey(item, callback) === key) return item;
		}

		throw new Error("When calling ko.update*, the key '" + key + "' was not found!");
	}

	function filterArrayByKey(array, callback) {
		return ko.utils.arrayMap(ko.utils.unwrapObservable(array), function (item) {
			if (callback) {
				return mapKey(item, callback);
			} else {
				return item;
			}
		});
	}

	function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
		if (exports.getType(rootObject) === "array") {
			for (var i = 0; i < rootObject.length; i++)
			visitorCallback(i);
		} else {
			for (var propertyName in rootObject)

View on GitHub (pinned to c67a80103a)

Solutions

  1. Refresh the underlying data fully so keys line up before updating.
  2. Verify the `key` callback reads a stable, unique field.
  3. Handle the missing case gracefully by reloading from server rather than updating in place.

Example fix

// before
// partial update referencing a key not present -> throws
ko.mapping.fromJS(partialData, viewModel);
// after - full refresh first
ko.mapping.fromJS(fullData, viewModel);
Defensive patterns

Strategy: validation

Validate before calling

// Verify a key exists before any update path that looks it up.
function keyExists(arr, key, keyCallback) {
  return ko.utils.unwrapObservable(arr).some(function (item) {
    return keyCallback(item) === key;
  });
}
if (!keyExists(viewModel, targetKey, keyCb)) {
  console.warn('Key not present; refreshing from server instead of updating');
  return refresh();
}

Type guard

function itemHasKey(arr, key, keyCallback) {
  return ko.utils.unwrapObservable(arr).some(function (i) { return keyCallback(i) === key; });
}

Try / catch

try {
  ko.mapping.fromJS(delta, viewModel);
} catch (e) {
  if (/key .* was not found/.test(e.message)) {
    console.warn('Stale view-model; doing full reload');
    return reloadAll();
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling a ko.update*/mappedUpdate path with data whose key is absent from the existing array; key callback returning different values for the same logical item before vs after; concurrent server edits removing the item.

Common situations: Stale client view-model; partial refresh that omits an item another part references; key extracted from different fields over time.

Related errors


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