{"record":{"id":"dad4d19e25ef68a0","repo":"dotnet/aspnetcore","slug":"cannot-create-a-jsobjectreference-from-the-value","errorCode":null,"errorMessage":"Cannot create a JSObjectReference from the value '${jsObject}'.","messagePattern":"Cannot create a JSObjectReference from the value '(.+?)'\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts","lineNumber":180,"sourceCode":"      if (jsObject === null || jsObject === undefined) {\n          return {\n              [jsObjectIdKey]: -1\n          };\n      }\n\n      if (jsObject && (typeof jsObject === \"object\" || jsObject instanceof Function)) {\n          cachedJSObjectsById[nextJsObjectId] = new JSObject(jsObject);\n\n          const result = {\n              [jsObjectIdKey]: nextJsObjectId\n          };\n\n          nextJsObjectId++;\n\n          return result;\n      }\n\n      throw new Error(`Cannot create a JSObjectReference from the value '${jsObject}'.`);\n  }\n\n  /**\n   * Creates a JavaScript data reference that can be passed to .NET via interop calls.\n   *\n   * @param streamReference The ArrayBufferView or Blob used to create the JavaScript stream reference.\n   * @returns The JavaScript data reference (this will be the same instance as the given object).\n   * @throws Error if the given value is not an Object or doesn't have a valid byteLength.\n   */\n  export function createJSStreamReference(streamReference: ArrayBuffer | ArrayBufferView | Blob | any): any {\n      let length = -1;\n\n      // If we're given a raw Array Buffer, we interpret it as a `Uint8Array` as\n      // ArrayBuffers' aren't directly readable.\n      if (streamReference instanceof ArrayBuffer) {\n          streamReference = new Uint8Array(streamReference);\n      }\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts#L162-L198","documentation":"Thrown by DotNet.createJSObjectReference() when the supplied value is not null, not undefined, and not a JS object or Function. The interop layer can only track references to real objects/functions; primitives cannot be cached by ID. Null/undefined short-circuit to a sentinel ID of -1, so this error only fires for non-object truthy values.","triggerScenarios":"Calling createJSObjectReference with a primitive: a string, number, boolean, or bigint. Also fires when a JS interop call is declared to return JSObjectReference in .NET ([JSInvokable] returning a string), because the runtime calls createJSCallResult -> createJSObjectReference on the return value.","commonSituations":"Returning a primitive from a JS interop function whose .NET caller expects IJSObjectReference; passing a plain string where DotNet expects an object reference; upgrading an interop method's return type from object to primitive without updating the .NET side.","solutions":["Wrap the primitive in an object before returning: return { value: myString };","Change the .NET interop return type from IJSObjectReference to the matching primitive (string, int, etc.) so createJSCallResult uses JSCallResultType.Default."],"exampleFix":"// before (JS interop function returning a primitive)\nDotNet.invokeMethodAsync('MyLib', 'GetToken').then(ref => {\n    // .NET declared IJSObjectReference -> createJSObjectReference('abc') throws\n});\n\n// after\n// .NET side: change Task<string> instead of Task<IJSObjectReference>\n// or JS side: return an object wrapper\nreturn { token: myToken };","handlingStrategy":"type-guard","validationCode":"function isObjectLike(v) { return v !== null && v !== undefined && (typeof v === 'object' || typeof v === 'function'); }\nif (!isObjectLike(value)) { throw new TypeError('Expected an object or function for JSObjectReference'); }\nconst ref = DotNet.createJSObjectReference(value);","typeGuard":"function isJSObjectReferenceable(v: unknown): v is object | Function { return v !== null && v !== undefined && (typeof v === 'object' || typeof v === 'function'); }","tryCatchPattern":"try { return DotNet.createJSObjectReference(value); } catch (e) { throw new Error(`Interop return value must be an object; got ${typeof value}.`, { cause: e }); }","preventionTips":["Ensure JS interop functions that map to IJSObjectReference return an object, not a primitive.","Keep .NET interop return types and JS return values in sync across refactors.","Wrap primitives in an object if a reference handle is truly required."],"tags":["js-interop","blazor","serialization","object-reference","dotnet"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}