{"record":{"id":"d54609db3dea453b","repo":"didi/DoKit","slug":"invalid-uri-uri","errorCode":null,"errorMessage":"Invalid uri: <uri>","messagePattern":"Invalid uri: <uri>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/ContactsPhotoRequestHandler.java","lineNumber":95,"sourceCode":"    Uri uri = data.uri;\n    switch (matcher.match(uri)) {\n      case ID_LOOKUP:\n        uri = ContactsContract.Contacts.lookupContact(contentResolver, uri);\n        if (uri == null) {\n          return null;\n        }\n        // Resolved the uri to a contact uri, intentionally fall through to process the resolved uri\n      case ID_CONTACT:\n        if (SDK_INT < ICE_CREAM_SANDWICH) {\n          return openContactPhotoInputStream(contentResolver, uri);\n        } else {\n          return ContactPhotoStreamIcs.get(contentResolver, uri);\n        }\n      case ID_THUMBNAIL:\n      case ID_DISPLAY_PHOTO:\n        return contentResolver.openInputStream(uri);\n      default:\n        throw new IllegalStateException(\"Invalid uri: \" + uri);\n    }\n  }\n\n  @TargetApi(ICE_CREAM_SANDWICH)\n  private static class ContactPhotoStreamIcs {\n    static InputStream get(ContentResolver contentResolver, Uri uri) {\n      return openContactPhotoInputStream(contentResolver, uri, true);\n    }\n  }\n}\n","sourceCodeStart":77,"sourceCodeEnd":106,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/ContactsPhotoRequestHandler.java#L77-L106","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nString uriStr = \"content://com.android.contacts/contacts/asdf/photo\"; // malformed lookup\nDokitPicasso.with(ctx).load(Uri.parse(uriStr)).into(img);\n\n// after\nCursor c = ctx.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,\n    new String[]{ContactsContract.Contacts.PHOTO_THUMBNAIL_URI},\n    ContactsContract.Contacts._ID + \"=?\", new String[]{contactId}, null);\nif (c != null && c.moveToFirst() && !c.isNull(0)) {\n  DokitPicasso.with(ctx).load(Uri.parse(c.getString(0))).into(img);\n} else {\n  img.setImageResource(R.drawable.default_avatar);\n}\nif (c != null) c.close();","handlingStrategy":"validation","validationCode":"// Prefer framework-provided photo URIs; if validating manually, match supported forms:\nstatic boolean isSupportedContactUri(Uri uri) {\n  if (uri == null || !\"content\".equals(uri.getScheme())) return false;\n  String p = uri.getPath();\n  return p != null && (p.matches(\"/contacts/[^/]+/photo\")\n      || p.contains(\"/display_photo\")\n      || p.matches(\"/contacts/[^/]+(/\\d+)?\"));\n}\nif (isSupportedContactUri(uri)) picasso.load(uri).into(img);\nelse img.setImageResource(R.drawable.default_avatar);","typeGuard":null,"tryCatchPattern":"try {\n  picasso.load(contactUri).error(R.drawable.default_avatar).into(img,\n      new Callback() {\n        @Override public void onSuccess() {}\n        @Override public void onError(Exception e) {\n          if (e instanceof IllegalStateException\n              && e.getMessage() != null && e.getMessage().startsWith(\"Invalid uri:\")) {\n            img.setImageResource(R.drawable.default_avatar);\n          }\n        }\n      });\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Invalid uri:\")) return;\n  throw e;\n}","preventionTips":["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"],"tags":["android","picasso","contacts","uri"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}