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

  1. Always derive the photo URI from the framework: use the PHOTO_URI / PHOTO_THUMBNAIL_URI columns returned by ContactsContract queries rather than building strings
  2. If you must construct, match one of the supported forms: contacts/<lookup_key>/<id>, contacts/<id>/photo, or display_photo
  3. 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

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


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