I have a very simple update here:

Document emailDoc = emailLogoDoc[0];
emailDoc.Body = newLogoData.emailLogo;
emailDoc.Url = Url.getSalesforceBaseUrl().getProtocol() + '://'+System.Url.getSalesforceBaseUrl().getHost().remove('-api')+'/servlet/servlet.ImageServer?id='+emailDoc.Id+'&oid='+UserInfo.getOrganizationId();
    update emailDoc;
}catch(DmlException e){
    system.debug(e.getDmlMessage(0) + ', Line: ' + e.getLineNumber());

If the document already exists (checking against the name). When it does exist, and is updating, I get the following error and the record fails to update

This Document Unique Name already exists or has been previously used. Please choose a different name.

This makes no sense to me... of course the Document Unique Name already exists, that is why it is being updated, not inserted! I am not changing the name, making a new document with the same name, etc... So I do not get why this error is occurring.

How do you properly update existing documents and insert new documents through apex? All I am really concerned with is setting the Url and Body and IsPublic to true.

(I am making an interface to allow users to upload images to be used for various things in other visualforce pages, so if an image already exists (then a document exists for it), just update, but if it doesn't exist, then I want to create a new one in apex, which is why I am doing this).


I am now able to create and update these documents. I wasn't adding the MIME type, which it apparently needed to recognize what kind of image it was and how to render it I guess. So, in the document folder, the documents are what they should be after being created or edited.

But now, those changes are not being reflected on the VF page when I refresh the page after updating.

In my controller, I do this to grab the image URL:

public String siteLogoUrl{
        List<Document> siteLogoDoc = [SELECT Id, Name, Url, Body FROM Document WHERE Name = 'SchedulerSiteLogo'];
        if(siteLogoDoc.size() > 0){
            return Url.getSalesforceBaseUrl().getProtocol() + '://'+System.Url.getSalesforceBaseUrl().getHost().remove('-api')+'/servlet/servlet.ImageServer?id='+siteLogoDoc[0].Id+'&oid='+UserInfo.getOrganizationId();
            //return siteLogoDoc.get(0).Url;
            return null;

Then do this in the VF page to render it:

<apex:image id="schedulerSiteLogo" value="{!siteLogoUrl}" rendered="{!siteLogoUrl != null}" title="Selected Logo" style="margin-left: 15px; margin-top: 15px; margin-bottom: 15px;" />

But it keeps displaying the old image and doesn't register the changes even though the changes took place in the actual document folder.

Is there a better way to pass a document to an apex:image? I couldn't figure out how to pass it the body of the document.

Another Update

Changing my URL to '/servlet/servlet.FileDownload?file=' + emailLogoDoc[0].Id; that my getter returns fixed this. The thing is that it takes a few minutes it seems for changes to actually take place. The files change in the document file, but you can reload right away and the images are not changed on the VF page. Then if you wait like 5 minutes and refresh, all the sudden everything is up to date and the images are changed how they should be......

2 Answers 2


You can upsert based on Name (but sadly, not developer name). You'll get an exception if the name is not unique, though:

upsert d Document.Name;

Also, you didn't actually specify a name, so you need to do that.

Finally, you can't do an update without an Id or an External ID; since you didn't specify an Id or an External Id, it tried to perform an insert, hence the error.

You could also query for the Document beforehand. Regardless, you need to provide all the necessary information for an update to occur.

  • If the assumption not correct Document emailDoc = emailLogoDoc[0]; that emailDoc will have the document to be updated?
    – Mahmood
    Sep 27, 2017 at 17:40
  • I query it like this before doing anything: List<Document> emailLogoDoc = [SELECT Id, Name, Url, Body FROM Document WHERE Name = 'SchedulerEmailLogo']; and trying upsert emailDoc Document.Name gave the same error. So I have the Name and Id in document already. I am just trying to change the body, then call update, but gives me this Document Unique Name is not Unique junk... Sep 27, 2017 at 18:54
  • And I just discovered my insert works fine. I added FolderId to the query to grab that, and queried the folder and added that to the document I create if none exists. It successfully created a new document. But it is still giving me that error on update. Sep 27, 2017 at 19:15
  • Added an update to my original post. Creating and updating seem to be working in the document folder, however, now the changes are not being reflected on my VF page, even after refreshing the page. Sep 27, 2017 at 20:48

The documentation specifies here,

If you enter URL, don't specify body or bodylength and if you specify body then don't specify URL.

So, you just need to specify URL in your case and remove the line where you are updating the body and see if that works.


For Test, I have created a document using apex, and updated it using the below code, and it is working

Document docToUpdate = [SELECT id, body FROM document WHERE createddate = today];
String myContent2 = 'updated body';
docToUpdate.body = Blob.valueOf(myContent2);
update docToUpdate;
  • Getting rid of setting the URL did not fix the problem unfortunately Sep 27, 2017 at 18:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .