Blankj/AndroidUtilCode · error · IllegalArgumentException

{} > {}

Error message

{} > {}

What it means

Thrown by CacheDiskUtils$cacheInner.copyOfRange when the 'from' argument exceeds 'to' (i.e., newLength = to - from < 0). This is a defensive guard mirroring java.util.Arrays.copyOfRange semantics, protecting the subsequent array allocation from a negative length. It indicates corrupted or unexpected time-info header parsing in the on-disk cache byte payload.

Source

Thrown at lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java:860

                try {
                    return Long.parseLong(millis) * 1000;
                } catch (NumberFormatException e) {
                    return -1;
                }
            }
            return -1;
        }

        private static byte[] getDataWithoutDueTime(final byte[] data) {
            if (hasTimeInfo(data)) {
                return copyOfRange(data, TIME_INFO_LEN, data.length);
            }
            return data;
        }

        private static byte[] copyOfRange(final byte[] original, final int from, final int to) {
            int newLength = to - from;
            if (newLength < 0) throw new IllegalArgumentException(from + " > " + to);
            byte[] copy = new byte[newLength];
            System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
            return copy;
        }

        private static boolean hasTimeInfo(final byte[] data) {
            return data != null
                    && data.length >= TIME_INFO_LEN
                    && data[0] == '_'
                    && data[1] == '$'
                    && data[12] == '$'
                    && data[13] == '_';
        }
    }
}

View on GitHub (pinned to 7b4caf9e54)

Solutions

  1. Clear the affected cache entry/directory so the malformed payload is regenerated.
  2. Ensure cache writes are atomic (write to temp then rename) to avoid truncated entries.
  3. Verify the utilcode version matches the version that wrote the cache (TIME_INFO_LEN is version-specific).
  4. Wrap cache reads in a try/catch and treat a malformed entry as a cache miss.

Example fix

// before
byte[] payload = cacheDiskUtils.getBytes(key); // from > to on corrupted entry

// after
byte[] payload;
try {
    payload = cacheDiskUtils.getBytes(key);
} catch (IllegalArgumentException ex) {
    cacheDiskUtils.remove(key); // drop the corrupted entry
    payload = null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// No caller-side validation fully prevents this (corruption is on disk).
// Best pre-check: confirm utilcode version matches the cache writer's version
// and that cache writes are atomic (write-to-temp + rename).

Try / catch

byte[] payload;
try {
    payload = cacheDiskUtils.getBytes(key);
} catch (IllegalArgumentException e) {
    // malformed time-info header -> treat as cache miss
    cacheDiskUtils.remove(key);
    payload = null;
}

Prevention

When it happens

Trigger: The cache data's time-info header (the '_$...$_' marker) reports a TIME_INFO_LEN start offset greater than the total data length, so copyOfRange(data, TIME_INFO_LEN, data.length) is called with from > to. Happens during getDataWithoutDueTime when hasTimeInfo returned true for a malformed/truncated entry.

Common situations: Disk-cache corruption (partial writes, app killed mid-write); cache format migration between utilcode versions where TIME_INFO_LEN changed; manually editing or truncating cache files; concurrent access to the cache directory without locking.

Related errors


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