1

I'm trying to create ContentNote records from Note ones but it's always giving me this particular error:

FATAL_ERROR System.UnexpectedException: Note can't be saved

Code:

List<Note> noteLIST = [SELECT Id, Title, Body, OwnerId, Owner.Profile.Name, ParentId, IsPrivate, CreatedById, CreatedDate FROM Note WHERE Owner.Profile.Name LIKE 'current_profile_i_want_to_check'];
List<ContentNote> cnLIST = new List<ContentNote>();
for(Note n : noteLIST){
    ContentNote cn = new ContentNote(Title = n.Title,
                                     Content = Blob.valueOf(n.Body));
    cnLIST.add(cn);
}
if(!cnLIST.isEmpty()){
    insert cnLIST;
}

I've checked this post: Help with "System.UnexpectedException: Note can't be saved" in batch apex but still not working.

2

I'm the author of the ContentNote library referred to in the linked answer. I'll reiterate the things I'm aware of that you need to do to prepare note content for insertion:

  1. Replace all basic HTML characters (<>"'&) with their corresponding entities (&amp; and friends).
  2. Replace all line breaks with <br> (taking care with Windows CRLF/Linux LF/Mac CR)
  3. Replace &apos; with &#39;.
  4. Do not replace Unicode characters with entities. Other entities, including &apos;, result in an exception. Unicode should be left as the bare characters.
  5. Ensure that the source content is well-formed Unicode/UTF-8 and does not contain non-printable characters.
  6. The title must not be null, zero-length, or consist only of whitespace. The title need not be escaped.

Also note that

the API reference on ContentNote incorrectly specifies to use String.escapeHTML4() to prepare content. This does not work.

Here's how I actually prepare notes there:

public void addNote(String title, String content, Id linkedTo, String visibility, String shareType) {
    ContentNote cn = new ContentNote();

    if (title != null && title.normalizeSpace().length() > 0) {
        cn.Title = title;
    } else {
        cn.Title = 'Untitled Note';
    }

    cn.Content = Blob.valueOf(content.escapeXML().replace('\r\n', '<br>').replace('\r', '<br>').replace('\n', '<br>').replace('&apos;', '&#39;'));

    // Go on to insert the ContentNote
}

If you don't precisely meet the expectations, you'll get an UnexpectedException, which is uncatchable and unhandleable in the same way as a LimitException.

Existing App

You may also want to look at Doug Ayers' existing application for converting classic Notes into ContentNotes.

| improve this answer | |
1

There are many things you need to reconsider in your code:-

  1. The contentNote object field Content is of type blob(base64) but you are trying to put string value. Use Blob.valueOf('')
  2. The createdById having properties as follows:- Create (for users assigned the Set Audit Fields Upon Creation permission), Defaulted on createFilter, Group, Sort, Update (for users assigned the Set Audit Fields Upon Creation permission). So if you have been assigned the Set Audit Fields Upon Creation permission, You can manipulate the CreatedBYId field.
  3. The CreatedDate having properties as follows:- Create (for users assigned the Set Audit Fields Upon Creation permission), Defaulted on createFilter, Group, Sort, Update (for users assigned the Set Audit Fields Upon Creation permission). So if you have been assigned the Set Audit Fields Upon Creation permission, You can manipulate the CreatedDate field.
  4. The OwnerId having properties as follows:- Create (for users assigned the Set Audit Fields Upon Creation permission), Defaulted on createFilter, Group, Sort, Update (for users assigned the Set Audit Fields Upon Creation permission). So if you have been assigned the Set Audit Fields Upon Creation permission, You can manipulate the OwnerId field.
  5. You may like to look on SharingPrivacy. It Controls sharing privacy for a file. Only administrators and file owners with Collaborator access to the file can modify this field. Default is Visible to Anyone With Record Access. When set to Private on Records, the file is private on records but can be shared selectively with others.
  6. Special Access Rules:- Enhanced Notes must be enabled.

As per your comments, below code might help you:-

ContentNote cn = new ContentNote();
cn.Title = 'test1';
String body = 'Hello World. Before insert/update, escape special characters such as ", ', &, and other standard escape characters.';
cn.Content = Blob.valueOf(body.escapeHTML4());
insert(cn);

The above code escapes any special characters so they are converted to their HTML equivalents.

Read more about them here:- ContentNote

| improve this answer | |
  • Thanks for your response! I have the Blob.valueOf(n.Body) in my code but didn't write it in first place. I also removed CreatedBy, CreatedDate and Owner fields but it's giving me same error again. – molinet Apr 3 '19 at 10:27
  • Can you make sure you have enabled the notes? – sanket kumar Apr 3 '19 at 10:34
  • Yes, It's enabled. What I've seen is that if my Note's Body has line breaks it displays the error. If not it creates ContentDocumentLink record successfully. Edit: exact error: System.UnexpectedException: Note can't be saved because it contains HTML tags or unescaped characters that are not allowed in a Note. – molinet Apr 3 '19 at 10:40
  • I have update in my answer. Please check them. – sanket kumar Apr 3 '19 at 10:44
  • Thanks for the update! I'll try this after a meeting and write you with the result. – molinet Apr 3 '19 at 10:53

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.