I experienced this issue myself and contacted AWS support. It seems that CloudFormation associates the logical ID with the resource, for example (using IAM as an example but many resources are the same):
exampleLogicalId:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
ManagedPolicyName: exampleName
...
Here, the resource gets created with a custom name (exampleName in this case). As long as the logical ID (exampleLogicalId) remains unchanged, CloudFormation will recognise that the resource has already been created and will update it as necessary.
However if you change the logical ID (as happened to me when using CDK, because it auto-generates these logical IDs) then CloudFormation thinks it needs to create a new resource. But because the name already exists, and for this resource type the names must be unique, there is a conflict and the creation fails. This seems to be because CloudFormation creates all new resources before deleting any removed ones.
The solution is to either 1) put the logical ID back to what it originally was so CloudFormation recognises it as an 'update' rather than a 'create', or 2) change the unique part (the exampleName in this example) to be something unique.
Changing the name (or whatever the unique field is for the resource in question) can be a convenient option, because it will create the new resource and associate it with the new logical ID, then delete the old resource if that logical ID no longer exists in your CloudFormation template. You can then rename the resource back to what you wanted originally (keeping the same logical ID) and deploy a second time, and CloudFormation will recognise it as an update operation, and rename the resource back to what you wanted the first time.
Just be aware that doing this will not perform an update, but rather a delete-then-create. So if your resource has data (e.g. DynamoDB table with data, IAM policy already attached to roles, Parameter Store entry with a value entered) you may need to recreate this data for the new resource.