{"record":{"id":"e0b15ad09e7e21ef","repo":"lingochamp/FileDownloader","slug":"huh-utf-8-should-be-supported","errorCode":null,"errorMessage":"Huh, UTF-8 should be supported?","messagePattern":"Huh, UTF-8 should be supported\\?","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/liulishuo/filedownloader/util/FileDownloadUtils.java","lineNumber":236,"sourceCode":"     *             directory to place the file;\n     *             If {@code pathAsDirectory} is {@code false}, {@code path} would be the absolute\n     *             file path.\n     * @return The download id.\n     */\n    public static int generateId(final String url, final String path,\n                                 final boolean pathAsDirectory) {\n        return CustomComponentHolder.getImpl().getIdGeneratorInstance()\n                .generateId(url, path, pathAsDirectory);\n    }\n\n    public static String md5(String string) {\n        byte[] hash;\n        try {\n            hash = MessageDigest.getInstance(\"MD5\").digest(string.getBytes(\"UTF-8\"));\n        } catch (NoSuchAlgorithmException e) {\n            throw new RuntimeException(\"Huh, MD5 should be supported?\", e);\n        } catch (UnsupportedEncodingException e) {\n            throw new RuntimeException(\"Huh, UTF-8 should be supported?\", e);\n        }\n\n        StringBuilder hex = new StringBuilder(hash.length * 2);\n        for (byte b : hash) {\n            if ((b & 0xFF) < 0x10) hex.append(\"0\");\n            hex.append(Integer.toHexString(b & 0xFF));\n        }\n        return hex.toString();\n    }\n\n\n    public static String getStack() {\n        return getStack(true);\n    }\n\n    public static String getStack(final boolean printLine) {\n        StackTraceElement[] stackTrace = new Throwable().getStackTrace();\n        return getStack(stackTrace, printLine);","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/util/FileDownloadUtils.java#L218-L254","documentation":"md5() encodes its input as UTF-8 before hashing and wraps UnsupportedEncodingException in a RuntimeException. Like MD5, UTF-8 is guaranteed on every Java/Android runtime, so this is a defensive guard that should never fire in practice. If it does, the platform charset support is broken.","triggerScenarios":"string.getBytes(\"UTF-8\") throws UnsupportedEncodingException during generateFileName — only possible on a JVM missing the UTF-8 charset, which the spec mandates.","commonSituations":"Extremely stripped custom runtimes; broken CharsetProvider registrations on embedded/non-standard JVMs. Essentially never seen on stock Android.","solutions":["Fix the runtime so the standard charsets are available (restore default charset providers).","If running on an exotic JVM, verify Charset.isSupported(\"UTF-8\") and repair the charset provider configuration.","As a fallback in app code, catch the RuntimeException and use string.getBytes(StandardCharsets.UTF_8) via your own hashing routine."],"exampleFix":"// before\nString name = FileDownloadUtils.generateFileName(url); // wraps UnsupportedEncodingException\n\n// after (own equivalent, no checked charset lookup)\nMessageDigest md = MessageDigest.getInstance(\"MD5\");\nbyte[] hash = md.digest(url.getBytes(StandardCharsets.UTF_8));","handlingStrategy":"try-catch","validationCode":"if (!Charset.isSupported(\"UTF-8\")) {\n    throw new IllegalStateException(\"Runtime is missing UTF-8 charset; FileDownloader md5 will fail\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    name = FileDownloadUtils.generateFileName(url);\n} catch (RuntimeException e) {\n    Log.e(\"FileDownloader\", \"UTF-8 charset unavailable\", e);\n    name = String.valueOf(url.hashCode());\n}","preventionTips":["Do not remove default charsets via custom ClassLoader/runtime trimming.","Run a startup sanity check (Charset.isSupported(\"UTF-8\")) on exotic runtimes.","Prefer StandardCharsets.UTF_8 APIs in your own code to sidestep the checked exception path."],"tags":["android","charset","utf-8","runtime-environment"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6237a8cac174bcc916e4342b14ab1ab72a5768d4","analyzedAt":"2026-09-08T23:50:48.168Z","contentChangedAt":"2026-09-08T23:50:48.168Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}