Is it possible to copy a ContentVersion image associated with one record so that the copy is associated with a different record?

Code below gives me the following Execute Anonymous error.:

Line: 12, Column: 1 System.DmlException: Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, Content cannot be inserted as a child of record 00641000009ZlV3.: [FirstPublishLocationId]

Opportunity opp; //original Opportunity record
Opportunity oppCopy; //copy of opp record with different id

for (ContentVersion img : [SELECT Id, Checksum, ContentDocumentId, ContentLocation, ContentModifiedById, ContentModifiedDate, ContentSize,  FileExtension, FileType, FirstPublishLocationId, IsAssetEnabled, IsLatest, IsMajorVersion, NegativeRatingCount, Origin, OwnerId, PathOnClient, PositiveRatingCount, PublishStatus, RatingCount, ReasonForChange, SharingOption, Title, VersionData, VersionNumber 
                           FROM ContentVersion 
                           WHERE FirstPublishLocationId =: opp.Id])
    insert new ContentVersion(Title = img.Title, PathOnClient = img.PathOnClient, 
                              VersionData = img.VersionData, 
                              FirstPublishLocationId = oppCopy.Id);
  • how you are creating this contentversion record? – Santanu Boral Apr 4 '17 at 5:12
  • The original record was created by uploading an image to an opportunity record directly into Salesforce. Looking at this record via SOQL, I see the FirstPublishLocationId corresponds to the Opportunity Id it was uploaded to. – DHG Apr 4 '17 at 13:42
  • N.B. you have DML inside a for loop - not good practice for bulk operations. That said, I would insert the new ContentVersion w/o FirstPublishedId and then construct ContentDocumentLinks between the new ContentVersion and oppCopy as that better mimics the way Files are associated with sobjects – cropredy Apr 5 '17 at 3:26

The below code works without throwing any errors: -

 ContentVersion  cont =[SELECT Checksum,ContentDocumentId,ContentLocation,ContentSize,ContentUrl,Description,FileExtension,FileType,FirstPublishLocationId,Id,IsAssetEnabled,IsDeleted,Origin,OwnerId,PathOnClient,PublishStatus,RatingCount,ReasonForChange,SharingOption,Title,VersionData,VersionNumber FROM ContentVersion WHERE ContentDocumentId = '06990000003Cq5V'];

 ContentVersion newcont = new ContentVersion();
 newcont.Title  = cont.Title;
 newcont.PathOnClient  = cont.PathOnClient;
 newcont.VersionData = cont.VersionData;
 newcont.FirstPublishLocationId  = cont.FirstPublishLocationId;

insert newcont;

But you are facing the issue because you are using Opportunity Id in "FirstPublishLocationId" field.

Per the description in the SOAP API documentation the FirstPublishLocationId field is the:

""" ID of the location where the version was first published. If the version is first published into a user's personal library or My Files, the field will contain the ID of the user who owns the personal library or My Files. If the first version is published into a public library, the field will contain the ID of that library.

This field is only set the first time a version is published via the API. It isn't set when a version is published in Salesforce CRM Content or uploaded in Salesforce Files or. After the version is published, it is a read-only field.

If you don't set a FirstPublishLocationId via the API, this field defaults to the user's personal library, unless Origin is set to H, then this field defaults to My Files. """ https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentversion.htm

Taking this into consideration when setting the FirstPublishLocationId should resolve the issue you're experiencing.

  • It looks like you are associating your copied ContentVersion to the same PublishLocation. I am trying to associate the copy to a different record. I had previously uploaded a file to my Opportunity and using SOQL can see the original upload has this Opportunity Id for its FirstPublishLocationId. It's odd to me I can't use another Opportunity's Id here – DHG Apr 4 '17 at 12:40

Insufficient Access would indicate that the user might not have permission on the field/record. Does it produce this error with a user that has "view all data" permission? Also, is the class that's executing utilizing the "with sharing" keyword? If so, what happens when you remove "with sharing" from the class?

  • I'm logged in with a System Administrator profile, which has View All Data enabled. Additionally, the 2 opportunity records I'm working with were created by me. I just put the above code into the Execute Anonymous window in the Developer Console, so there isn't a class containing this yet. – DHG Apr 4 '17 at 2:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.