dotnet/aspnetcore · error · Error
Could not find ' ' (' ' was undefined).
Error message
Could not find '${identifier}' ('${key}' was undefined). What it means
Thrown by DotNet.findObjectMember() while traversing dotted identifiers (e.g. 'document.location.href') when an intermediate segment is missing on the current object. The function walks all keys except the last; if any intermediate key is absent or current is not an object, the path is broken and the identifier cannot resolve.
Solutions
- Verify the full dotted path exists in the browser console at call time: window.myApp.helper.doThing.
- Ensure the JS library is loaded before the .NET interop call (load in wwwroot index.html, await Blazor start).
- Correct typos or renamed APIs in the .NET Invoke identifier string.
Example fix
// before (C#)
await JS.InvokeVoidAsync("myApp.helpers.doThing");
// JS only exposes window.myApp.doThing
// after (C# matches the real path)
await JS.InvokeVoidAsync("myApp.doThing"); Defensive patterns
Strategy: validation
Validate before calling
// In JS, expose a helper that asserts the path exists before .NET calls it.
function pathExists(root, dotted) { let c = root; for (const k of dotted.split('.')) { if (!c || !(k in c)) return false; c = c[k]; } return true; } Type guard
function hasMember(root: any, dotted: string): boolean { let c = root; for (const k of dotted.split('.')) { if (c == null || !(k in c)) return false; c = c[k]; } return true; } Try / catch
try { await JS.InvokeVoidAsync("myApp.helper.doThing"); } catch (JSException e) when (e.Message.Contains("Could not find")) { /* log identifier, ensure script loaded */ } Prevention
- Load JS libraries before Blazor makes interop calls (place scripts in wwwroot index.html).
- Double-check dotted identifiers against the actual JS object graph in the console.
- After library upgrades, re-verify identifier paths used in .NET Invoke strings.
When it happens
Trigger: .NET invokes a JS member by dotted identifier and one of the intermediate segments doesn't exist, e.g. calling 'myApp.helper.doThing' when window.myApp exists but myApp.helper is undefined. The error names the first missing intermediate key.
Common situations: JS library loaded conditionally or asynchronously and not present when interop runs; typo in the identifier on the .NET side; library API renamed between versions; script tag ordering issues.
Related errors
- The property ' ' is not defined or is not readable.
- The property ' ' is not writable.
- The value ' ' is not a function.
- Byte array index ' ' does not exist.
- Cannot create a JSObjectReference from the value
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/b770fd11af5b83f3.
Report an issue: GitHub.
Appendix: source
Thrown at src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts:604
* Traverses the object hierarchy to find an object member specified by the identifier.
*
* @param obj Root object to search in.
* @param identifier Complete identifier of the member to find, e.g. "document.location.href".
* @returns A tuple containing the immediate parent of the member and the member name.
*/
export function findObjectMember(obj: any, identifier: string): [any, string] {
const keys = identifier.split(".");
let current = obj;
// First, we iterate over all but the last key. We throw error for missing intermediate keys.
// Error handling in case of undefined last key depends on the type of operation.
for (let index = 0; index < keys.length - 1; index++) {
const key = keys[index];
if (current && typeof current === "object" && key in current) {
current = current[key];
} else {
throw new Error(`Could not find '${identifier}' ('${key}' was undefined).`);
}
}
return [
current,
keys[keys.length - 1]
];
}
// Takes an object member and a call type and returns a function that performs the operation specified by the call type on the member.
//
// @param parent Immediate parent of the accessed object member.
// @param memberName Name (key) of the accessed member.
// @param callType The type of the operation to perform on the member.
// @param identifier The full member identifier. Only used for error messages.
// @returns A function that performs the operation on the member.
//
function wrapJSCallAsFunction(parent: any, memberName: string, callType: JSCallType, identifier: string): Function {View on GitHub (pinned to 3600ca084e)