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.js's internal `getItemByKey` iterates a mapped array and throws when no element's `mapKey` equals the requested key. It backs `ko.update*` operations that locate an item by key before updating it.

Source

Thrown at aspnetcore/mvc/controllers/testing/samples/3.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. Confirm the key passed matches what the configured `key` callback extracts (same property name and type).
  2. Check existence with `mappedIndexOf` before attempting the keyed update.
  3. Refresh the mapped array from the server before updating so the target key is present.
  4. Normalize key casing and type (string vs number) on both sides.

Example fix

// before
updateByKey(mappedArray, '42', patch);

// after
if (mappedArray.mappedIndexOf({ id: 42 }) !== -1) {
  updateByKey(mappedArray, '42', patch);
}
Defensive patterns

Strategy: validation

Validate before calling

function safeUpdateByKey(mappedArray, key, callback, patch) {
  if (mappedArray.mappedIndexOf({ /* match shape */ }) === -1) {
    throw new Error('Key not present: ' + key);
  }
  // proceed with keyed update
}

Type guard

function keyExists(mappedArray, key, keyCallback) {
  return filterArrayByKey(mappedArray, keyCallback).indexOf(key) !== -1;
}

Try / catch

try {
  updateByKey(arr, key, cb, patch);
} catch (e) {
  if (/was not found/.test(e.message)) {
    refreshFromServer(); // re-sync then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling a key-based update (e.g. via the mapping plugin's keyed update path) with a key that does not match any element returned by the configured key callback.

Common situations: Key callback returns a different property than the caller used (id vs _id); item was removed from the array before the update; stale client-side state referencing a deleted record; case mismatch in key values.

Related errors


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