Skip to content

bird live sync does not persist profile avatar URLs from GraphQL user payloads #71

Description

@Gatsby1s

Summary

When syncing live data through the bird transport, Birdclaw creates/updates profile rows for timeline, likes, bookmarks, and mentions authors, but many of those profile rows are persisted without avatar_url. The web UI then falls back to initial/letter avatars even though the raw bird --json-full GraphQL payload contains usable avatar URLs.

Environment

  • birdclaw: 0.8.5 installed via Homebrew
  • bird: 0.8.0 installed via Homebrew
  • transport: bird / Chrome cookie-backed GraphQL
  • database: fresh-ish local store without archive import, live sync via birdclaw sync * --mode bird

Reproduction

  1. Initialize Birdclaw and configure a bird transport account.
  2. Sync live data, for example:
birdclaw sync timeline --mode bird --limit 50 --refresh --json
birdclaw sync likes --mode bird --limit 20 --refresh --json
birdclaw sync bookmarks --mode bird --limit 20 --refresh --json
birdclaw sync mentions --mode bird --limit 20 --refresh --json
  1. Inspect profile avatar coverage for synced tweets/collections:
SELECT e.kind,
       COUNT(*) total,
       SUM(CASE WHEN p.avatar_url IS NOT NULL AND p.avatar_url <> '' THEN 1 ELSE 0 END) with_avatar
FROM tweet_account_edges e
JOIN tweets t ON t.id = e.tweet_id
JOIN profiles p ON p.id = t.author_profile_id
GROUP BY e.kind;

SELECT c.kind,
       COUNT(*) total,
       SUM(CASE WHEN p.avatar_url IS NOT NULL AND p.avatar_url <> '' THEN 1 ELSE 0 END) with_avatar
FROM tweet_collections c
JOIN tweets t ON t.id = c.tweet_id
JOIN profiles p ON p.id = t.author_profile_id
GROUP BY c.kind;

Observed before local repair:

home|50|1
mention|3|0
thread_context|6|2
bookmarks|20|0
likes|20|0

The Home UI showed letter/initial placeholders for most authors.

Raw data evidence

Running bird home --following -n 5 --json-full includes avatar URLs under the raw GraphQL user payload, for example:

{
  "core": {
    "user_results": {
      "result": {
        "rest_id": "1197424631398879233",
        "avatar": {
          "image_url": "https://pbs.twimg.com/profile_images/..._normal.jpg"
        },
        "core": {
          "screen_name": "Franktradinglog",
          "name": "Frank trading"
        }
      }
    }
  }
}

So the source data exists; it appears to be dropped or not mapped when normalizing bird live-sync users into profiles.avatar_url.

Expected behavior

When the bird transport receives a GraphQL user object with avatar.image_url, Birdclaw should persist it to profiles.avatar_url for the matching profile_user_<rest_id> row, and the web UI should render real avatars through /api/avatar?....

Local workaround used

I repaired my local DB by parsing bird --json-full outputs for timeline/likes/bookmarks/mentions, extracting (rest_id, avatar.image_url), then backfilling only empty profiles.avatar_url rows.

After backfill:

home|50|50
mention|3|3
thread_context|6|6
bookmarks|20|20
likes|20|20

The UI then rendered /api/avatar?profileId=...&v=https%3A%2F%2Fpbs.twimg.com%2Fprofile_images... images as expected.

Suggested fix

In the bird transport normalization path, map GraphQL user.result.avatar.image_url into the profile upsert model as avatarUrl, preserving existing avatar URLs when the live payload does not include one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossThis issue is about lost, corrupted, or silently dropped user/session/config data.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions