bumptech/glide · warning · FileNotFoundException

Contact cannot be found

Error message

Contact cannot be found

What it means

When loading a contact photo via a lookup Uri or phone-number lookup Uri, StreamLocalUriFetcher first calls ContactsContract.Contacts.lookupContact to resolve the lookup key to a real contact Uri. If lookupContact returns null, no contact matches the lookup key (the contact was deleted, merged, or the key is invalid), and Glide throws a FileNotFoundException.

Source

Thrown at library/src/main/java/com/bumptech/glide/load/data/StreamLocalUriFetcher.java:85

      throws FileNotFoundException {
    InputStream inputStream = loadResourceFromUri(uri, contentResolver);
    if (inputStream == null) {
      throw new FileNotFoundException("InputStream is null for " + uri);
    }
    return inputStream;
  }

  private InputStream loadResourceFromUri(Uri uri, ContentResolver contentResolver)
      throws FileNotFoundException {
    switch (URI_MATCHER.match(uri)) {
      case ID_CONTACTS_CONTACT:
        return openContactPhotoInputStream(contentResolver, uri);
      case ID_CONTACTS_LOOKUP:
      case ID_LOOKUP_BY_PHONE:
        // If it was a Lookup uri then resolve it first, then continue loading the contact uri.
        uri = ContactsContract.Contacts.lookupContact(contentResolver, uri);
        if (uri == null) {
          throw new FileNotFoundException("Contact cannot be found");
        }
        return openContactPhotoInputStream(contentResolver, uri);
      case ID_CONTACTS_THUMBNAIL:
      case ID_CONTACTS_PHOTO:
      case UriMatcher.NO_MATCH:
      default:
        if (useMediaStoreApisIfAvailable
            && MediaStoreUtil.isMediaStoreUri(uri)
            && MediaStoreUtil.isMediaStoreOpenFileApisAvailable()) {
          return openMediaStoreFileInputStream(uri, contentResolver);
        } else {
          return contentResolver.openInputStream(uri);
        }
    }
  }

  private InputStream openContactPhotoInputStream(ContentResolver contentResolver, Uri contactUri) {
    return ContactsContract.Contacts.openContactPhotoInputStream(

View on GitHub (pinned to eb14a895d8)

Solutions

  1. Do not persist contact lookup Uris across sessions; re-resolve from contact ID or lookup key each time
  2. Handle FileNotFoundException gracefully and show a default avatar placeholder
  3. Verify the contact still exists via a fresh lookupContact query before loading the photo
  4. Use .fallback() to show a default person silhouette when no contact photo is available

Example fix

// before
Glide.with(context).load(storedLookupUri).into(avatarView);
// after — re-resolve and handle missing contact
Glide.with(context)
  .load(storedLookupUri)
  .fallback(R.drawable.ic_default_avatar)
  .error(R.drawable.ic_default_avatar)
  .into(avatarView);
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify contact exists before loading photo
private boolean contactExists(ContentResolver cr, Uri lookupUri) {
  Uri contactUri = ContactsContract.Contacts.lookupContact(cr, lookupUri);
  return contactUri != null;
}
if (contactExists(getContentResolver(), lookupUri)) {
  Glide.with(context).load(lookupUri).into(avatarView);
}

Try / catch

Glide.with(context)
  .load(lookupUri)
  .fallback(R.drawable.ic_default_avatar)
  .error(R.drawable.ic_default_avatar)
  .listener(new RequestListener<Drawable>() {
    @Override public boolean onLoadFailed(GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
      for (Throwable cause : e.getRootCauses()) {
        if (cause instanceof FileNotFoundException && cause.getMessage().contains("Contact cannot be found")) {
          Log.w(TAG, "Contact no longer exists: " + model);
        }
      }
      return false;
    }
    @Override public boolean onResourceReady(Drawable r, Object m, Target<Drawable> t, DataSource d, boolean i) { return false; }
  })
  .into(avatarView);

Prevention

When it happens

Trigger: Loading a contact photo using a stale ContactsContract.Contacts.CONTENT_LOOKUP_URI from a previous session. The contact was deleted or merged after the lookup Uri was stored. A phone number lookup Uri that does not match any contact.

Common situations: Apps that cache contact lookup Uris across sessions. Sync or backup/restore operations that change contact IDs. Contact was deleted by the user or another app between storing the Uri and loading the photo. Phone number lookups for numbers not in the user's contacts.

Related errors


AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14). Data as JSON: /api/errors/c0f1ce7ef4f575f8. Report an issue: GitHub.