didi/DoKit · error · IllegalArgumentException

byteSize shouldn't be less than zero!

Error message

byteSize shouldn't be less than zero!

What it means

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.

Source

Thrown at Android/dokit-util/src/main/java/com/didichuxing/doraemonkit/util/ConvertUtils.java:474

    public static String byte2FitMemorySize(final long byteSize) {
        return byte2FitMemorySize(byteSize, 3);
    }

    /**
     * Size of byte to fit size of memory.
     * <p>to three decimal places</p>
     *
     * @param byteSize  Size of byte.
     * @param precision The precision
     * @return fit size of memory
     */
    @SuppressLint("DefaultLocale")
    public static String byte2FitMemorySize(final long byteSize, int precision) {
        if (precision < 0) {
            throw new IllegalArgumentException("precision shouldn't be less than zero!");
        }
        if (byteSize < 0) {
            throw new IllegalArgumentException("byteSize shouldn't be less than zero!");
        } else if (byteSize < MemoryConstants.KB) {
            return String.format("%." + precision + "fB", (double) byteSize);
        } else if (byteSize < MemoryConstants.MB) {
            return String.format("%." + precision + "fKB", (double) byteSize / MemoryConstants.KB);
        } else if (byteSize < MemoryConstants.GB) {
            return String.format("%." + precision + "fMB", (double) byteSize / MemoryConstants.MB);
        } else {
            return String.format("%." + precision + "fGB", (double) byteSize / MemoryConstants.GB);
        }
    }

    /**
     * Time span in unit to milliseconds.
     *
     * @param timeSpan The time span.
     * @param unit     The unit of time span.
     *                 <ul>
     *                 <li>{@link TimeConstants#MSEC}</li>

View on GitHub (pinned to 626827cddb)

Solutions

  1. Clamp to 0 when negatives are expected: Math.max(0, byteSize).
  2. Check upstream sentinel values (-1) from size queries and handle them as errors before formatting.
  3. Order subtraction correctly (larger - smaller) when computing deltas.

Example fix

// before
long used = total - free; // may be negative if computed wrongly
String s = ConvertUtils.byte2FitMemorySize(used, 3);

// after
long used = Math.max(0, total - free);
String s = ConvertUtils.byte2FitMemorySize(used, 3);
Defensive patterns

Strategy: validation

Validate before calling

long safe = Math.max(0, byteSize);
String s = ConvertUtils.byte2FitMemorySize(safe, precision);

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/3c71dbeba8db1557. Report an issue: GitHub.