1

We are attempting to upload a CSV containing local drive links to text files and html files. We want these to become "Content Notes". Data Loader keeps throwing errors when we attempt to upload (see below images.) Are we missing something?

Thanks.

Example of csv file:
Please note that the OwnerID is currently the external ID, but we've also tried using a Salesforce Account ID. Same issue.

OwnerID,Title,DateCreated,Content
abc-000118000023053985051C,Interested in buying,4/24/1995 17:52,C:\Attachments\MaxExport_3.txt

enter image description here enter image description here enter image description here

  • What error message exactly you got in the error log file? what kind of id are you giving for the owner id? – sanket kumar Sep 16 '18 at 18:04
  • We've tried Account Id, same issue. Error log has just the headers, OWNERID TITLE,DATECREATED,CONTENTERROR – SFExplorer Sep 16 '18 at 18:10
  • We were thinking that it may be related to trying to edit the audit fields (?), we found some Trailblazer stuff that indicates this is not possible for Notes. Alternatively, if it is, perhaps the formatting? – SFExplorer Sep 16 '18 at 18:14
1

Ultimately, only Salesforce can explain exactly what that specific gack message means. However, it appears to have to do with a misunderstanding about attaching the ContentNote records to parent files.

The OwnerId field is the User who owns the Note, not the record to which it is attached. You're not required to populate this field. In fact, it's often ideal to allow Salesforce to populate the field based on your data load user, if you use an "Integration User"- or "System User"-type model. This can be helpful because of the unique permission structure on Content objects, which can result in you being unable to access or modify the inserted records immediately after you assign ownership to another user.

Rather than populating a parent object Id in the OwnerId field, in order to attach the Note to a record, you need to perform a second Data Loader pass to insert ContentDocumentLink records.

ContentDocumentLink acts as a junction object between the ContentNote and the various locations where it may be shared. (When working with Content objects, you can generally treat ContentNote and ContentDocument as equivalent. ContentNote abstracts away some of the complexity around adding versions and extracting their document Ids to add links).

Salesforce has detailed instructions on how to perform these two data-load passes. Basically, you'll get your success file back from Data Loader after inserting the Notes (which, after the first step, are not linked to anything) and then use it to construct the second load file (for ContentDocumentLink).

You treat the output Id column of the inserted Notes as the ContentDocumentId field of the ContentDocumentLink. You then have to populate a couple of other fields to define the share type - see the documentation for more (sometimes confusing) details, but I've found that the appropriate solution is to set ShareType = "I" and Visibility = "AllUsers". Lastly, you put the parent Id in the LinkedEntityId field.

One way to simplify your process here will be to include all of these columns (ShareType, Visibility, and LinkedEntityId) in your original import file. You'd simply not map them in the first load pass. Then, when you open your success file, each inserted ContentNote Id would still be clearly associated with its desired LinkedEntityId. By simply changing the Id column that Data Loader outputs to ContentDocumentId, you could feed that success file straight into Data Loader's column auto-match for a ContentDocumentLink import.

I have written an open source package to support bulk imports of Content Notes, which might be useful or an example.

  • Phew, finally some logic to this! Thanks David, this clearly addresses the issue. We'll look into this over the next few days, might end up sending you a PM if you don't mind. Since we are limited to exporting 1000 rows, and yet we are importing 120k notes, we'll have to use a solution like this to get those IDs back. (Do correct me if my understanding here is flawed.) Thanks again! – SFExplorer Sep 16 '18 at 20:58
  • David, to clarify further, when we export the IDs how do we know which note it's attached to? Must the titles then be unique? Or are the absolute paths of the file location maintained. – SFExplorer Sep 16 '18 at 21:02
  • Forgive me if I am misunderstanding - but you don't need to do a separate export pass, so I don't follow the 1k record restriction. I'll edit in a suggestion regarding tracking notes through the multi-step import process. – David Reed Sep 16 '18 at 21:10
  • Ahh I misunderstood, apologies David. So the initial load will produce the new ContentDocumentID's in the success file (that's great), and then THOSE id's are what goes into the second load. The LinkedEntityID...is this where the External ID goes? IE: Account.External_Id__c ? Or must it be a Salesforce Account Id. – SFExplorer Sep 16 '18 at 21:47
  • (1): correct, success file yields your ContentDocumentIds. (2): You should be able to use an External Id for LinkedEntityId and perform an upsert, but I can't say I've tried it myself. I don't make bets on how Content works because the rules are often different than with other objects. – David Reed Sep 16 '18 at 22:16
0

OwnerId will accept only the user id. Try with any user id, else everything looks fine. Even if you don't provide it, the ContentNote will get created with the owner as the current user id.

OwnerId Properties:- Create (for users assigned the Set Audit Fields Upon Creation permission), Defaulted on create, Filter, Group, Sort, Update (for users assigned the Set Audit Fields Upon Creation permission)

Also, As you are doing upsert operation, the ownerId cannot be updated. Make sure of this point.

Refer this:- https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentnote.htm

Hope it helps you.

  • Thanks Sanket. In that case, how do we make sure the Notes are attached to the proper Account they are related to? – SFExplorer Sep 16 '18 at 19:07

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.