1. `copy_cache` in `models.py` recursively copies the caches to environment, 
2. which in
```python
def _compute_related(self, records):
        """ Compute the related field ``self`` on ``records``. """
        others = records.sudo() if self.related_sudo else records
        if records.env != others.env:
            copy_cache(records - records.filtered('id'), others.env)
        values = list(others)
        for name in self.related[:-1]:
            values = [first(value[name]) for value in values]
        for record, value in zip(records, values):
            record[self.name] = value[self.related_field.name]
```
3. copies failing cache values that have been produce previously by this line:

`models.py : def _prefetch_field()`
```python

        try:
            # THIS ONE
            result = records.read([f.name for f in fs], load='_classic_write')
        except AccessError:
            # not all records may be accessible, try with only current record
            result = self.read([f.name for f in fs], load='_classic_write')
```
I checked it's exactly the same `FailedValue` object, which is later accessed without intent (not refreshed) by the fact that the buggy environment is copied to sudo (and not refreshed).


odoo/fields.py
""" Return the dependencies of ``self`` as tuples ``(model, field, path)``,
            where ``path`` is an optional list of field names.
        """
        model0 = model
        result = []
        
        for dotnames in self.depends:
            if dotnames == self.name:
                _logger.warning("Field %s depends on itself; please fix its decorator @api.depends().", self)
            model, path = model0, dotnames.split('.')
            for i, fname in enumerate(path):
                field = model._fields[fname]
                result.append((model, field, path[:i]))
                model = model0.env.get(field.comodel_name)
        
        for mname, fnames in model0._depends.iteritems():
            model = model0.env[mname]
            for fname in fnames:
                field = model._fields[fname]
                result.append((model, field, None))
        
        for model, field, path in list(result):
            for inv_field in model._field_inverses[field]:
                inv_model = model0.env[inv_field.model_name]
                inv_path = None if path is None else path + [field.name]
                result.append((inv_model, inv_field, inv_path))
        return result
    def setup_triggers(self, model):