117

I'm trying to call

parent.postMessage(obj, 'whatever');

from within an iframe and I'm getting this error: Uncaught DOMException: Failed to execute 'postMessage' on 'Window': An object could not be cloned.

nieve
  • 4,601
  • 3
  • 20
  • 26
  • 2
    This happens all the time, if something can not be duplicated by the structured clone algorithm. This algorithm is used by `window.postMessage`. For more information see my **[answer with solution and detailed explanation why it happans](https://stackoverflow.com/a/52223341)**. – Bharata Sep 28 '18 at 11:51

2 Answers2

196

It turns out the object I passed had methods, which is why the error message said An object could not be cloned.

In order to fix this, you can do the following:

obj = JSON.parse(JSON.stringify(obj));
parent.postMessage(obj, 'whatever');
nieve
  • 4,601
  • 3
  • 20
  • 26
  • 13
    That's good to know, because Mozilla says messages are serialized for you: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage Makes sense it wouldn't know how to serialize a function... – jonobr1 Apr 07 '17 at 21:19
  • 4
    were you able to access methods on that object after passing to parent?? – Prakash Palnati Jul 30 '18 at 09:45
  • 2
    Note that doing so you'll crash on cyclics (which should be preserved by postMessage) instead of on functions. – Kaiido Sep 05 '18 at 07:45
  • 1
    In my case the problem were caused by an nonexistent variable passed in parameters. – Daniel Santana Oct 02 '18 at 08:46
  • When using AngularJS, I found this solution removed fields that were of TrustedValueHolderType. I'm looking for a solution for dealing with this. – PatS Nov 15 '18 at 21:19
  • My semi-cheap catch all hack around this is to stringify the payload and convert again on recieving, strips out the unparsable junk. – Jamie Nicholl-Shelley Sep 19 '22 at 00:58
  • Your answer is really helpful Thank you! – ran ia Jun 15 '23 at 09:08
0

Depending on the data you're trying to pass, a more surgical approach could be to use simpler data structures that are compatible with postMessage().

The following will throw the error since postMessage can't serialize SetIterator:

let s = new Set();
parent.postMessage({s: s.values()}, '*');

The following will work as expected since postMessage can serialize Array:

let s = new Set();
parent.postMessage({s: [...s]}, '*');

This approach works more in line with the intent of implicit serialization by postMessage(). When you need more complex data structures or can't be bothered to get all surgical, the good ole JSON.stringify/parse hammer works just fine ;)

OXiGEN
  • 2,041
  • 25
  • 19