internetarchive / internetarchive/openlibrary

Avatar endpoint returns broken image for accounts with no linked IA itemname

Open
#13,248 3 comments 0 reactions 1 assignee Claimed by @richardmilles View on GitHub
Affects: Server Affects: UI Lead: @mekarpeles Needs: Review Assignee Priority: 3 Type: Bug
Dominant language
Python
Stars
6.7k
Forks
2k
Avg merge
2d 19h
Merged PRs (30d)
138

Description

### Problem

Patron avatars render as a broken image whenever the account has **no** linked Internet Archive `internetarchive_itemname`. The `/people//avatar` endpoint interpolates the literal Python `None` into the redirect URL, producing `https://archive.org/services/img/None`, which Internet Archive returns as `403 Forbidden`.

This affects every place a patron avatar is shown for such accounts (list-follow cards on book pages, follows/followers pages, etc.). Example account: `mykaelus`.

### Reproducing the bug

1. Go to a page that renders a patron avatar for a user with no linked IA itemname, e.g. https://openlibrary.org/books/OL7950851M/Warcraft_World_of_Warcraft (the "Borrow Wishlist" list-follow card, owner `@mykaelus`)
2. Alternatively, request the avatar endpoint directly: https://openlibrary.org/people/mykaelus/avatar
3. Observe the network request / the rendered image

* Expected behavior: a default/placeholder avatar image is served
* Actual behavior: the endpoint returns `303 See Other` → `location: https://archive.org/services/img/None`, which returns `403 Forbidden`, so the browser shows a broken-image icon and logs `avatar:1 Failed to load resource: the server responded with a status of 403`

```
$ curl -sI https://openlibrary.org/people/mykaelus/avatar
HTTP/1.1 303 See Other
location: https://archive.org/services/img/None

$ curl -sI https://archive.org/services/img/None
HTTP/1.1 403 Forbidden
```

### Context

- Browser (Chrome, Safari, Firefox, etc): Any (reproduced in Brave/Chromium)
- OS (Windows, Mac, etc): Any
- Logged in (Y/N): N (not required)
- Environment (prod, dev, local): prod

### Breakdown

Implementation Details (for maintainers)

`User.get_avatar_url()` reads `internetarchive_itemname` from the account and unconditionally builds `https://archive.org/services/img/{itemname}`. When the account has no linked IA item, `itemname` is `None`, so the URL becomes `.../img/None` (a guaranteed 403). Notably the surrounding `cache.memoize` already anticipates this value via `cacheable=lambda key, value: not value.endswith("/None")`, but the function still returns the broken URL instead of a fallback.

Suggested fix: short-circuit when `itemname` is falsy instead of returning a URL that always 403s:

```python
itemname = user.get_account().get("internetarchive_itemname")
if not itemname:
return # see note below
return f"https://archive.org/services/img/{itemname}"
```

Note on the default: there is currently **no** user-avatar placeholder asset in the repo. `static/images/icons/` only contains `avatar_author-lg.png`, `avatar_author.png`, `avatar_book-lg.png`, `avatar_book-sm.png`, and `avatar_book.png`. So a fix needs either (a) a new user-avatar asset added and returned here, or (b) reuse of an existing asset — maintainers to decide which. No `onerror` fallback exists on any of the `` tags today either, so adding one in the templates below would be a defense-in-depth complement.

#### Requirements Checklist
* [ ] `get_avatar_url` returns a default avatar when no `internetarchive_itemname` is linked
* [ ] Broken-image icon no longer appears for such accounts

#### Related files
* `openlibrary/core/models.py` — `User.get_avatar_url()` (interpolates `None`)
* `openlibrary/plugins/upstream/mybooks.py` — `avatar` route (`/people/([^/]+)/avatar`)
* `openlibrary/templates/lists/list_follow.html` — renders `` with no fallback

#### Stakeholders
*


#### Instructions for Contributors

- Please [run these commands](https://docs.openlibrary.org/developers/tools/git.html#working-on-your-branch) to ensure your repository is up to date **before** [creating a new branch](https://docs.openlibrary.org/developers/tools/git.html#making-changes-and-creating-a-pull-request) to work on this issue and **each time after** pushing code to Github, because the pre-commit bot may add commits to your PRs upstream.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.