System.UnexpectedException
gets thrown a lot with Note inserts if you do not prepare the content exactly right, and they cannot be caught or handled in any way.
I wrote an open source package a while ago to abstract over some of these issues. From its documentation, a summary of the requirements:
The following steps are required to prepare note content for insertion into Salesforce:
- Replace all basic HTML characters (
<>"'&
) with their corresponding entities (&
and friends).
- Replace all line breaks with
<br>
(taking care with Windows CRLF/Linux LF/Mac CR)
- Replace
'
with '
.
- Do not replace Unicode characters with entities. Other entities, including
'
, result in an exception. Unicode should be left as the bare characters.
- Ensure that the source content is well-formed Unicode/UTF-8 and does not contain non-printable characters.
- The title must not be
null
, zero-length, or consist only of whitespace. The title need not be escaped.
So while I don't have an answer to (1), the answer to (2) is "yes."
The skeleton of the code that I worked out to avoid the issue looks like this:
public void addNote(String title, String content, Id linkedTo, String visibility, String shareType) {
ContentNote cn = new ContentNote();
if (title != null && title.normalizeSpace().length() > 0) {
// A null, zero-length, or all-whitespace title will result in an UnexpectedException on insert.
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(''', '''));
insert cn;
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = cn.Id;
cdl.LinkedEntityId = linkedTo;
cdl.Visibility = visibility;
cdl.ShareType = shareType;
insert cdl;
}
UnexpectedException
is supposed to be thrown when you do something Salesforce wants to force you to stop doing, like calling the Object constructor. Maybe they want to stop developers from putting unescaped user input into notes.