didi/DoKit · error · IllegalStateException
Invalid uri: <uri>
Error message
Invalid uri: <uri>
What it means
ContactsPhotoRequestHandler.fetch(Uri, ContentResolver) switches on the contacts URI's matcher ID (ID_CONTACT, ID_THUMBNAIL, ID_DISPLAY_PHOTO). Any contacts-looking URI the static CONTACT_URI_MATCHER does not recognize falls to default and throws IllegalStateException('Invalid uri: ' + uri). It means the URI passed the 'is this a contact photo URI' pre-check but its specific form is not one of the three supported shapes.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/ContactsPhotoRequestHandler.java:95
Uri uri = data.uri;
switch (matcher.match(uri)) {
case ID_LOOKUP:
uri = ContactsContract.Contacts.lookupContact(contentResolver, uri);
if (uri == null) {
return null;
}
// Resolved the uri to a contact uri, intentionally fall through to process the resolved uri
case ID_CONTACT:
if (SDK_INT < ICE_CREAM_SANDWICH) {
return openContactPhotoInputStream(contentResolver, uri);
} else {
return ContactPhotoStreamIcs.get(contentResolver, uri);
}
case ID_THUMBNAIL:
case ID_DISPLAY_PHOTO:
return contentResolver.openInputStream(uri);
default:
throw new IllegalStateException("Invalid uri: " + uri);
}
}
@TargetApi(ICE_CREAM_SANDWICH)
private static class ContactPhotoStreamIcs {
static InputStream get(ContentResolver contentResolver, Uri uri) {
return openContactPhotoInputStream(contentResolver, uri, true);
}
}
}
View on GitHub (pinned to 626827cddb)
Solutions
- Always derive the photo URI from the framework: use the PHOTO_URI / PHOTO_THUMBNAIL_URI columns returned by ContactsContract queries rather than building strings
- If you must construct, match one of the supported forms: contacts/<lookup_key>/<id>, contacts/<id>/photo, or display_photo
- Fall back for unmatched URIs: catch the IllegalStateException and load a placeholder or query the photo via ContactsContract.Contacts.openContactPhotoInputStream
Example fix
// before
String uriStr = "content://com.android.contacts/contacts/asdf/photo"; // malformed lookup
DokitPicasso.with(ctx).load(Uri.parse(uriStr)).into(img);
// after
Cursor c = ctx.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
new String[]{ContactsContract.Contacts.PHOTO_THUMBNAIL_URI},
ContactsContract.Contacts._ID + "=?", new String[]{contactId}, null);
if (c != null && c.moveToFirst() && !c.isNull(0)) {
DokitPicasso.with(ctx).load(Uri.parse(c.getString(0))).into(img);
} else {
img.setImageResource(R.drawable.default_avatar);
}
if (c != null) c.close(); Defensive patterns
Strategy: validation
Validate before calling
// Prefer framework-provided photo URIs; if validating manually, match supported forms:
static boolean isSupportedContactUri(Uri uri) {
if (uri == null || !"content".equals(uri.getScheme())) return false;
String p = uri.getPath();
return p != null && (p.matches("/contacts/[^/]+/photo")
|| p.contains("/display_photo")
|| p.matches("/contacts/[^/]+(/\d+)?"));
}
if (isSupportedContactUri(uri)) picasso.load(uri).into(img);
else img.setImageResource(R.drawable.default_avatar); Try / catch
try {
picasso.load(contactUri).error(R.drawable.default_avatar).into(img,
new Callback() {
@Override public void onSuccess() {}
@Override public void onError(Exception e) {
if (e instanceof IllegalStateException
&& e.getMessage() != null && e.getMessage().startsWith("Invalid uri:")) {
img.setImageResource(R.drawable.default_avatar);
}
}
});
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid uri:")) return;
throw e;
} Prevention
- Take photo URIs from ContactsContract PHOTO_URI / PHOTO_THUMBNAIL_URI columns, never hand-built strings
- Never persist contact photo URIs across OS upgrades; re-query them
- Assume OEM ContactsProviders may emit unsupported variants and always keep a placeholder path
When it happens
Trigger: Loading a contact photo URI obtained from ContactsContract but built with an unsupported path (e.g. a raw contacts lookup variant or a vendor-specific URI); passing a content://com.android.contacts/ URI whose path segments do not match photos/lookup/display_photo or contacts/<id>; string-built URIs with typos in the path.
Common situations: OEM-specific ContactsProvider path variations; URI persisted from an older Android version and replayed on a new one; manually constructing contact URIs instead of using ContactsContract.Contacts.CONTENT_URI-built helpers.
Related errors
- Unrecognized type of request: " + request
- No package provided: " + data.uri
- No path segments: " + data.uri
- Last path segment is not a resource ID: " + data.uri
- More than two path segments: " + data.uri
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/d54609db3dea453b.
Report an issue: GitHub.