Blankj/AndroidUtilCode · error · IllegalArgumentException

byteSize shouldn't be less than zero!

Error message

byteSize shouldn't be less than zero!

What it means

ConvertUtils.byte2FitMemorySize(long, int) formats a byte count into B/KB/MB/GB. A negative byteSize is physically meaningless for a memory/file size and would format a bogus negative string, so the method rejects it with IllegalArgumentException. The byteSize check runs only after the precision check passes.

Source

Thrown at lib/utilcode/src/main/java/com/blankj/utilcode/util/ConvertUtils.java:473

    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 7b4caf9e54)

Solutions

  1. Guard the size at the source: if size < 0, treat it as unknown (e.g. show "unknown"/"—") instead of formatting it.
  2. Clamp to 0 with Math.max(0, byteSize) when a negative value should be shown as zero bytes.
  3. Verify the File/StatFs you read the size from actually exists and is readable before computing the value passed in.
  4. Distinguish the -1 'error' return contract of getFreeSpace()/length() from real sizes upstream.

Example fix

// before
String s = ConvertUtils.byte2FitMemorySize(file.getFreeSpace(), 2); // getFreeSpace() may be -1

// after
long free = file.getFreeSpace();
String s = free < 0 ? "unknown" : ConvertUtils.byte2FitMemorySize(free, 2);
Defensive patterns

Strategy: validation

Validate before calling

// Validate byteSize before formatting
long byteSize = source.getFreeSpace(); // may be -1
if (byteSize < 0) {
    // treat as unknown rather than format
    return "unknown";
}
return ConvertUtils.byte2FitMemorySize(byteSize, precision);

Type guard

// Reject negative sizes at the boundary
public static boolean isValidSize(long size) {
    return size >= 0;
}

Try / catch

try {
    String s = ConvertUtils.byte2FitMemorySize(byteSize, precision);
} catch (IllegalArgumentException e) {
    // byteSize was negative; report unknown
    s = "unknown";
}

Prevention

When it happens

Trigger: Passing a negative long to byte2FitMemorySize — e.g. a File.length() proxy that returns -1 on error, a subtraction that underflows (freeSpace - usedSpace when used > free), or an unset sentinel value of -1.

Common situations: Using File.getFreeSpace()/getUsableSpace() which can return -1 on error or for nonexistent paths; arithmetic on disk stats where used exceeds total; defaulting an 'unknown size' field to -1; reading a size from a damaged header.

Related errors


AI-assisted analysis of Blankj/AndroidUtilCode@7b4caf9e54 (2026-08-14). Data as JSON: /api/errors/331df06975517621. Report an issue: GitHub.