`bw serve` returns an empty item list with `success: true` right after a sync
Steps To Reproduce
Log in and unlock a vault that contains at least one item, then start the API:
bw serve --hostname 127.0.0.1 --port 8087Run a forced sync followed by a list, one request after the other:
for i in $(seq 1 10); do curl --silent --request POST 'http://127.0.0.1:8087/sync?force=true' > /dev/null printf 'round %2d: ' "$i" curl --silent http://127.0.0.1:8087/list/object/items | jq --compact-output '[.success, (.data.data | length)]' sleep 2 doneThe same with 8 clients in parallel makes it far more likely:
for round in $(seq 1 5); do printf 'round %d: ' "$round" for i in $(seq 1 8); do ( curl --silent --request POST 'http://127.0.0.1:8087/sync?force=true' > /dev/null curl --silent http://127.0.0.1:8087/list/object/items | jq '.data.data | length' ) & done | tr '\n' ' ' wait echo sleep 5 done
?force=true only makes every sync a full sync. Without it the same happens whenever the vault changed on the server since the last sync, which in an organization vault shared with others is the normal case.
Expected Result
Every GET /list/object/items returns all items of the vault. If the list cannot be served, the response should fail instead of reporting success: true.
Actual Result
Some responses report success: true with an empty list, although the vault contains the item. A few seconds later the same request returns the item again.
Output with a vault containing exactly one item (bw 2026.9.0, official Bitwarden cloud server):
### serial
round 1: [true,1]
...
round 9: [true,1]
round 10: [true,0]
### parallel
round 1: 1 0 1 1 1 1 1 1
round 2: 0 0 1 1 1 1 1 1
round 3: 1 0 1 1 1 1 1 1
round 4: 1 1 1 0 1 1 1 1
round 5: 1 1 1 1 1 1 1 11 of 10 serial and 5 of 40 parallel responses were empty. In the same window, GET /object/item/<id> for the existing item answered 400 Bad Request. Earlier runs with 2026.8.0 showed the same (13 of 80 empty responses with 8 parallel clients and forced syncs, 4 of 80 without force).
Screenshots or Videos
No response
Additional Context
Impact: automation that treats "not in the list" as "does not exist" creates the item again. We hit this with an Ansible lookup plugin that creates a missing login item through bw serve: it produced duplicates of items that had existed for months, and the next run then failed on the ambiguous match.
Operating System
Linux
Operating System Version
Rocky Linux 9.8 (container)
Shell
Bash
Build Version
2026.9.0 (also reproduced with 2026.8.0)
Issue Tracking Info
- I understand that work is tracked outside of GitHub. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.
Source: bitwarden/clients