{"record":{"id":"5d88f36f0907f42d","repo":"parallax/jsPDF","slug":"character-at-position-position-of-string-text","errorCode":null,"errorMessage":"Character at position {position} of string '{text}' exceeds 16bits. Cannot be encoded into UCS-2 BE","messagePattern":"Character at position (.+?) of string '(.+?)' exceeds 16bits\\. Cannot be encoded into UCS-2 BE","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/jspdf.js","lineNumber":2650,"sourceCode":"    // isUnicode may be set to false above. Hence the triple-equal to undefined\n    while (isUnicode === undefined && i !== 0) {\n      if (text.charCodeAt(i - 1) >> 8) {\n        /* more than 255 */\n        isUnicode = true;\n      }\n      i--;\n    }\n    if (!isUnicode) {\n      return text;\n    }\n\n    newtext = flags.noBOM ? [] : [254, 255];\n    for (i = 0, l = text.length; i < l; i++) {\n      ch = text.charCodeAt(i);\n      bch = ch >> 8; // divide by 256\n      if (bch >> 8) {\n        /* something left after dividing by 256 second time */\n        throw new Error(\n          \"Character at position \" +\n            i +\n            \" of string '\" +\n            text +\n            \"' exceeds 16bits. Cannot be encoded into UCS-2 BE\"\n        );\n      }\n      newtext.push(bch);\n      newtext.push(ch - (bch << 8));\n    }\n    return String.fromCharCode.apply(undefined, newtext);\n  };\n\n  var pdfEscape = (API.__private__.pdfEscape = API.pdfEscape = function(\n    text,\n    flags\n  ) {\n    /**","sourceCodeStart":2632,"sourceCodeEnd":2668,"githubUrl":"https://github.com/parallax/jsPDF/blob/a3930ce03a585a26b2c76d12a0f413ce96f6d1a3/src/jspdf.js#L2632-L2668","documentation":"Thrown by the UCS-2 BE text encoder used when embedding Unicode strings into the PDF content stream. The loop walks each character, splits its code unit into high/low bytes, and guards against any code unit wider than 16 bits. In practice this guard is effectively unreachable: String.prototype.charCodeAt always returns a value in 0-65535, so (ch >> 8) >> 8 is always 0 for a normal JS string. It exists as a defensive assertion over the encoder's 16-bit assumption.","triggerScenarios":"Reached only if `text.charCodeAt(i)` somehow yields a value > 0xFFFF before `bch >> 8` is evaluated. With a standard ECMAScript string this cannot happen; it would require a non-string `text` or a tampered/host engine. The isUnicode flag must be true (font flagged as Unicode) to enter this branch.","commonSituations":"Essentially never observed in real usage because charCodeAt is bounded at 16 bits. If reported, it usually indicates the stack trace is stale, the text argument was not a real string, or a fork modified the encoding path.","solutions":["Confirm `text` is a genuine JavaScript string before calling the text/encoding API (e.g. String(value)).","If you maintain a fork, replace charCodeAt with codePointAt-aware logic or remove the dead guard once you are sure inputs are strings.","Report upstream only if you can reproduce with a plain string literal — include the exact character and code unit value."],"exampleFix":"// before\npdf.text(someValue, x, y); // someValue may not be a string\n// after\npdf.text(String(someValue), x, y);","handlingStrategy":"validation","validationCode":"if (typeof text !== 'string') text = String(text);\n// Optionally strip/replace characters; charCodeAt is always <=0xFFFF so the guard is effectively unreachable.\npdf.text(text, x, y);","typeGuard":"function isSafeString(v) { return typeof v === 'string'; }","tryCatchPattern":null,"preventionTips":["Always coerce text arguments to String before passing to jsPDF text APIs.","Do not pass objects, numbers, or undefined into the text encoding path.","Know that this specific guard is effectively unreachable with normal JS strings."],"tags":["encoding","ucs-2","text","unreachable","unicode"],"backgroundTag":null,"analyzedSha":"a3930ce03a585a26b2c76d12a0f413ce96f6d1a3","analyzedAt":"2026-08-13T05:33:39.648Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}