There are two osv class methods: copy and copy_data, which are accessible to all osv subclasses, such as your crm_lead_external class.

When you click Duplicate it calls osv.copy(). If your model contains any relational fields and those fields have any records linked then osv will call copy_data() on the linked records. In your case, when you call copy on model crm.lead, it calls copy_data() on crm_lead_external. You have a UNIQUE constraint on crm_lead_external, and that causes your error message.

There can be two fixes to this problem.

  1. If you don’t want to copy crm_lead_external records, then override the copy method of the crm.lead model and disable copying of the crm_lead_externaloem field values.
    def copy(self, cr, uid, id, default=None, context=None): if default is None: default = {} default['o2m_field'] = [] return super(<calss_name>, self).copy(cr, uid, id, default, context) 

    This will stop copying the o2m field record.

  2. We will override the copy method of your model crm_lead_extenal so every time copy_datais called, we will resolve the UNIQUE constraint stuff and and pass new values so you will not encounter any issues.
    def copy_data(self, cr, uid, id, default=None, context=None): if default is None: default = {} default['name'] = self.browse(cr, uid, id, context=context).name or '' if not context.get('copy',False): new_name = _("%s (copy)")%default.get('name','') default.update({'name':new_name}) return super(<calss_bame>, self).copy_data(cr, uid, id, default, context) 

    In this example, I have appended copy text at the end of the name so I will always get a new name, likewise you can avoid UNIQUE constraints like this, and you will have all the data copied perfectly