{"record":{"id":"3c71dbeba8db1557","repo":"didi/DoKit","slug":"bytesize-shouldn-t-be-less-than-zero","errorCode":null,"errorMessage":"byteSize shouldn't be less than zero!","messagePattern":"byteSize shouldn't be less than zero!","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Android/dokit-util/src/main/java/com/didichuxing/doraemonkit/util/ConvertUtils.java","lineNumber":474,"sourceCode":"    public static String byte2FitMemorySize(final long byteSize) {\n        return byte2FitMemorySize(byteSize, 3);\n    }\n\n    /**\n     * Size of byte to fit size of memory.\n     * <p>to three decimal places</p>\n     *\n     * @param byteSize  Size of byte.\n     * @param precision The precision\n     * @return fit size of memory\n     */\n    @SuppressLint(\"DefaultLocale\")\n    public static String byte2FitMemorySize(final long byteSize, int precision) {\n        if (precision < 0) {\n            throw new IllegalArgumentException(\"precision shouldn't be less than zero!\");\n        }\n        if (byteSize < 0) {\n            throw new IllegalArgumentException(\"byteSize shouldn't be less than zero!\");\n        } else if (byteSize < MemoryConstants.KB) {\n            return String.format(\"%.\" + precision + \"fB\", (double) byteSize);\n        } else if (byteSize < MemoryConstants.MB) {\n            return String.format(\"%.\" + precision + \"fKB\", (double) byteSize / MemoryConstants.KB);\n        } else if (byteSize < MemoryConstants.GB) {\n            return String.format(\"%.\" + precision + \"fMB\", (double) byteSize / MemoryConstants.MB);\n        } else {\n            return String.format(\"%.\" + precision + \"fGB\", (double) byteSize / MemoryConstants.GB);\n        }\n    }\n\n    /**\n     * Time span in unit to milliseconds.\n     *\n     * @param timeSpan The time span.\n     * @param unit     The unit of time span.\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}</li>","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit-util/src/main/java/com/didichuxing/doraemonkit/util/ConvertUtils.java#L456-L492","documentation":"byte2FitMemorySize rejects negative byteSize with IllegalArgumentException because a negative memory size is physically meaningless and cannot be mapped onto the B/KB/MB/GB ladder. The check runs after the precision check, so a call with both invalid arguments reports precision first.","triggerScenarios":"Passing a negative byte count: byte2FitMemorySize(usedMemory - maxMemory, 3) when used > max; deltas like freeMemory() - totalMemory() if computed in the wrong order; upstream APIs returning -1 on failure and being forwarded unfiltered.","commonSituations":"Memory-diff calculations in performance-monitoring tools (this library is DoraemonKit, a diagnostics toolkit); file sizes from failed stat() calls returning -1; progress calculations producing negative remainders.","solutions":["Clamp to 0 when negatives are expected: Math.max(0, byteSize).","Check upstream sentinel values (-1) from size queries and handle them as errors before formatting.","Order subtraction correctly (larger - smaller) when computing deltas."],"exampleFix":"// before\nlong used = total - free; // may be negative if computed wrongly\nString s = ConvertUtils.byte2FitMemorySize(used, 3);\n\n// after\nlong used = Math.max(0, total - free);\nString s = ConvertUtils.byte2FitMemorySize(used, 3);","handlingStrategy":"validation","validationCode":"long safe = Math.max(0, byteSize);\nString s = ConvertUtils.byte2FitMemorySize(safe, precision);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check for -1 sentinels from size queries before formatting.","Clamp memory/file deltas to zero at the computation site."],"tags":["formatting","validation","memory"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}