nostra13/Android-Universal-Image-Loader · error · IllegalArgumentException
URI [%1$s] doesn't have expected scheme [%2$s]
Error message
URI [%1$s] doesn't have expected scheme [%2$s]
What it means
Scheme.crop() (on the Scheme enum inside ImageDownloader) strips a known prefix like "http://" from a URI and throws IllegalArgumentException if the URI doesn't actually start with that scheme's prefix. It is a strict precondition: you must only call crop() on URIs already verified to belong to that scheme (typically via belongsTo() or Scheme.ofUri()). The format embeds both the offending URI and the expected scheme.
Source
Thrown at library/src/main/java/com/nostra13/universalimageloader/core/download/ImageDownloader.java:85
}
}
}
return UNKNOWN;
}
private boolean belongsTo(String uri) {
return uri.toLowerCase(Locale.US).startsWith(uriPrefix);
}
/** Appends scheme to incoming path */
public String wrap(String path) {
return uriPrefix + path;
}
/** Removed scheme part ("scheme://") from incoming URI */
public String crop(String uri) {
if (!belongsTo(uri)) {
throw new IllegalArgumentException(String.format("URI [%1$s] doesn't have expected scheme [%2$s]", uri, scheme));
}
return uri.substring(uriPrefix.length());
}
}
}
View on GitHub (pinned to ba33ec64d0)
Solutions
- Guard crop() with belongsTo() (or match on Scheme.ofUri(uri)) before calling it
- Use the correct enum constant for the URI you hold — HTTPS.crop for https:// URIs
- Keep data symmetric: only crop values produced by wrap(), and wrap again before displayImage
- Normalize URIs to a known scheme at the data boundary (DB/model layer) so crop sites can trust them
Example fix
// before
String path = Scheme.HTTP.crop(uri); // throws if uri is https:// or file://
// after
Scheme scheme = Scheme.ofUri(uri);
if (scheme == Scheme.HTTP) {
String path = Scheme.HTTP.crop(uri);
} else {
throw new IllegalArgumentException("Unexpected scheme for " + uri);
} Defensive patterns
Strategy: validation
Validate before calling
String prefix = scheme.wrap(""); // e.g. "http://"
if (uri != null && uri.toLowerCase(Locale.US).startsWith(prefix)) {
String path = scheme.crop(uri);
} else {
throw new IllegalArgumentException("URI " + uri + " is not " + prefix);
} Type guard
private static boolean belongsToScheme(String uri, ImageDownloader.Scheme scheme) {
return uri != null && uri.toLowerCase(Locale.US).startsWith(scheme.wrap(""));
} Try / catch
try {
path = Scheme.HTTP.crop(uri);
} catch (IllegalArgumentException e) {
// URI/expected scheme mismatch: re-detect scheme or reject the record
LOG.warn("Wrong scheme for {}", uri);
path = uri;
} Prevention
- Always pair crop() with a belongsTo()/ofUri() check in the same expression
- Store URIs together with their scheme, or never store cropped forms
- Use switch on Scheme.ofUri(uri) instead of assuming one constant
- Unit-test crop/wrap round-trips over your persisted data set
When it happens
Trigger: Calling Scheme.HTTP.crop(uri) on a URI like "file:///path" or "https://host" (HTTPS cropped with the HTTP enum); calling crop() before checking belongsTo(); calling crop(""+id) where the stored value never had the scheme appended (forgetting wrap() on the same data path).
Common situations: Persisting cropped IDs and later re-cropping them a second time; mixed http/https data where the wrong enum constant is used; deserialized URIs whose scheme changed between write and read; defensive-code refactors that moved crop() before the scheme check.
Related errors
- ImageAware should wrap ImageView. ImageViewAware is expected
- UIL doesn't support scheme(protocol) by default [%s]. You sh
- cacheDir argument must be not null
- fileNameGenerator argument must be not null
- maxSize <= 0
AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14).
Data as JSON: /api/errors/7b839e7faa4af0cd.
Report an issue: GitHub.