Hi Luciano, In chapter 22 you mention that `FrozenJSON.__getattr__()` raising a `KeyError` is "not to confusing". However, today I discovered a side effect from this that __is__ confusing: `copy.copy(FrozenJSON({'name': 'Jim Bo', 'class': 1982}))` raises a `RecursionError`. Indeed the documentation states that an `AttributeError` should be raised (https://docs.python.org/3/reference/datamodel.html#object.__getattr__) and apparently this is relied upon in the stdlib. In the copy implementation a new instance of `FrozenJSON` is generated without the initializer being called. Then, when looking for some optional dunder methods (that are not found) the copy implementation triggers a `__getattr__` call with `self.__data` not yet existing, triggering the recursion. What I appreciate in your book is that you are always very precise about all types of unexpected side effects, so maybe you could consider spending some text on this in a future update. Best regards, Michiel