element-hq / element-hq/synapse
Cannot add Avatar to Application Service
- Dominant language
- Python
- Stars
- 4.6k
- Forks
- 600
- Avg merge
- 5d 22h
- Merged PRs (30d)
- 51
Description
### Description
Calling `PUT /_matrix/client/v3/profile/{userId}/avatar_url?user_id={userId}` with an appservice token for a virtual user that has no existing profile row causes Synapse to crash with
```
TypeError: 'NoneType' object is not subscriptable` in `_check_profile_size
```
The upload step succeeds; only the profile `PUT` fails.
### Steps to reproduce
1. Register an application service via `app_service_config_files` in `homeserver.yml`
2. User can send "Hello, world!" to private room on synapse
3. Upload picture with `POST /_matrix/media/v3/upload?filename=&user_id=@:`
4. Call `PUT /_matrix/client/v3/profile/@:/avatar_url?user_id=@:` with the AS token
5. Synapse returns HTTP 500
### Homeserver
private homeserver
### Synapse Version
v1.151.0
### Installation Method
Docker (matrixdotorg/synapse)
### Database
PostgreSQL 18.1, single server, no SQLite migration
### Workers
Single process
### Platform
Ubuntu 24.04 (based on kernel 6.8), running in Docker container
### Configuration
_No response_
### Relevant log output
```shell
admin@my-homeserver:~$ docker logs matrix-synapse 2>&1 | grep -A20 "TypeError\|_check_profile_size\|ProfileField"
2026-04-16 20:24:50,818 - synapse.http.server - 147 - ERROR - PUT-21527 - Failed handle request via 'ProfileFieldRestServlet':
Traceback (most recent call last):
File "/usr/local/lib/python3.13/site-packages/synapse/http/server.py", line 335, in _async_render_wrapper
callback_return = await self._async_render(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.13/site-packages/synapse/http/server.py", line 576, in _async_render
callback_return = await raw_callback_return
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.13/site-packages/synapse/rest/client/profile.py", line 212, in on_PUT
await self.profile_handler.set_avatar_url(
user, requester, new_value, by_admin=is_admin, propagate=propagate
)
File "/usr/local/lib/python3.13/site-packages/synapse/handlers/profile.py", line 364, in set_avatar_url
await self.store.set_profile_avatar_url(target_user, avatar_url_to_set)
File "/usr/local/lib/python3.13/site-packages/synapse/storage/databases/main/profile.py", line 435, in set_profile_avatar_url
await self.db_pool.runInteraction(
"set_profile_avatar_url", set_profile_avatar_url
)
File "/usr/local/lib/python3.13/site-packages/synapse/storage/database.py", line 1015, in runInteraction
return await delay_cancellation(_runInteraction())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--
self._check_profile_size(
~~~~~~~~~~~~~~~~~~~~~~~~^
txn, user_id, ProfileFields.AVATAR_URL, new_avatar_url
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/usr/local/lib/python3.13/site-packages/synapse/storage/databases/main/profile.py", line 354, in _check_profile_size
(row[0] - 1 if row[0] else 0)
~~~^^^
TyError: 'NoneType' object is not subscriptable
```
### Anything else that would be useful to know?
_No response_
Contributor guide
Research direction
Start in synapse/storage/databases/main/profile.py at _check_profile_size and set_profile_avatar_url, following the call from handlers/profile.py and rest/client/profile.py. Reproduce the application-service avatar PUT with a virtual user lacking a profile row, then verify the request no longer returns HTTP 500 and the avatar URL is stored successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend, database
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100