{"record":{"id":"4f9d5e7f66c092fe","repo":"maotoumao/MusicFree","slug":"btoa-failed-the-string-to-be-encoded-contains-c","errorCode":null,"errorMessage":"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.","messagePattern":"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/utils/base64.ts","lineNumber":21,"sourceCode":"// @flow\n// Inspired by: https://github.com/davidchambers/Base64.js/blob/master/base64.js\n\nconst chars =\n    \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\nconst Base64 = {\n    btoa: (input: string = \"\") => {\n        let str = input;\n        let output = \"\";\n\n        for (\n            let block = 0, charCode, i = 0, map = chars;\n            str.charAt(i | 0) || ((map = \"=\"), i % 1);\n            output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))\n        ) {\n            charCode = str.charCodeAt((i += 3 / 4));\n\n            if (charCode > 0xff) {\n                throw new Error(\n                    \"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.\",\n                );\n            }\n\n            block = (block << 8) | charCode;\n        }\n\n        return output;\n    },\n\n    atob: (input: string = \"\") => {\n        let str = input.replace(/[=]+$/, \"\");\n        let output = \"\";\n\n        if (str.length % 4 == 1) {\n            throw new Error(\n                \"'atob' failed: The string to be decoded is not correctly encoded.\",\n            );","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/maotoumao/MusicFree/blob/d118b18b3d0c904400f7eea7bf99c0ceec6c1aee/src/utils/base64.ts#L3-L39","documentation":"The pure-JS btoa polyfill in src/utils/base64.ts throws this when any character code in the input string exceeds 0xFF (non-Latin1, e.g. Chinese text, emoji). Browser btoa has the same restriction; the polyfill replicates it. Input must be a binary/Latin1 string, not arbitrary UTF-8 text.","triggerScenarios":"Calling btoa(str) where str contains characters with code point > 255 — e.g. base64-encoding a JSON payload containing Chinese lyrics/titles, emoji, or any non-ASCII text.","commonSituations":"Encoding user-entered Chinese song names or config strings; encoding a UTF-8 string that was never percent-encoded or byte-converted first; porting browser code that assumed ASCII-only input.","solutions":["Convert the string to UTF-8 bytes first: btoa(unescape(encodeURIComponent(str))) or use TextEncoder + manual base64.","Better: add a utf8ToB64 helper in base64.ts that encodes via encodeURIComponent/unescape before the loop.","If the payload is data, encode bytes (Uint8Array) instead of a JS string."],"exampleFix":"// before\nconst encoded = btoa(JSON.stringify(payload));\n// after\nconst encoded = btoa(unescape(encodeURIComponent(JSON.stringify(payload))));","handlingStrategy":"validation","validationCode":"function isLatin1(str) {\n  for (let i = 0; i < str.length; i++) if (str.charCodeAt(i) > 0xff) return false;\n  return true;\n}\nif (!isLatin1(payload)) payload = unescape(encodeURIComponent(payload));","typeGuard":null,"tryCatchPattern":"try {\n  return btoa(str);\n} catch (e) {\n  if (String(e).includes('Latin1')) return btoa(unescape(encodeURIComponent(str)));\n  throw e;\n}","preventionTips":["Never pass raw user text (Chinese, emoji) directly to btoa; UTF-8 encode first.","Use a utf8ToB64/utf8SafeBtoa helper consistently across the codebase.","For binary data, base64-encode Uint8Array bytes instead of JS strings.","Add a unit test encoding a multilingual string."],"tags":["base64","encoding","utf-8","polyfill"],"backgroundTag":"btoa-latin1-range-error","analyzedSha":"d118b18b3d0c904400f7eea7bf99c0ceec6c1aee","analyzedAt":"2026-08-30T11:49:12.932Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}