Skip to content

X moved routes into /i/ namespace — URLChangedError on likes, bookmarks, DMs; indexTweets silently returns 0 #693

Description

@bylukeO
  • I have searched open and closed issues for duplicates
  • I am submitting a bug report for existing functionality that does not work as intended
  • This isn't a security bug

Describe the bug

X appears to have moved several routes into an /i/ namespace, which breaks multiple index jobs. Three fail loudly with URLChangedError; a fourth fails silently.

Confirmed redirects:

  • https://x.com/{username}/likeshttps://x.com/i/history/likes (breaks indexLikes)
  • https://x.com/i/bookmarkshttps://x.com/i/history (breaks indexBookmarks)
  • https://x.com/messageshttps://x.com/i/chat (breaks indexConversations)

indexTweets does not redirect and does not error, but completes having saved 0 tweets on an account that has tweets. I suspect the page markup changed alongside the routing changes, so the scraper finds nothing and exits cleanly.

Net effect: I can't build a local database at all, so I can't get to the delete step.

To Reproduce

  1. Add an X account and sign in
  2. Start Build Local Database with likes, bookmarks, DMs and tweets selected
  3. indexLikes throws URLChangedError; deselect likes
  4. indexBookmarks throws URLChangedError; deselect bookmarks
  5. indexConversations throws URLChangedError; deselect DMs
  6. Run with tweets only — job completes with no error and 0 tweets saved

Expected behavior

Jobs follow the new URLs and index normally.

Desktop:

  • OS: Linux (Linux Mint, installed from the Debian repo)
  • Version of Cyd: 1.1.22

Additional context

Full error JSON for all three URLChangedError cases below. Username redacted as {username}.


1. indexLikes

Details:

{
  "error": "URL changed from https://x.com/{username}/likes to https://x.com/i/history/likes\n\nURLChangedError: URL changed from https://x.com/{username}/likes to https://x.com/i/history/likes\n    at L_ (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:277:2261)\n    at async iv (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:277:20745)\n    at async Proxy.runJob (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:4596)\n    at async Proxy.run (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:8864)\n    at async E (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:10977)\n    at async de (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:722:24214)"
}

Context:

{
  "logs": [
    {
      "timestamp": "2026-08-17T05:18:26.932Z",
      "func": "runJob",
      "message": "running job indexLikes"
    },
    {
      "timestamp": "2026-08-17T05:18:26.939Z",
      "func": "loadBlank"
    },
    {
      "timestamp": "2026-08-17T05:18:26.939Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:18:27.142Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:18:27.188Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:18:27.389Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:18:29.394Z",
      "func": "loadURLWithRateLimit",
      "message": [
        "https://x.com/{username}/likes",
        [],
        false
      ]
    },
    {
      "timestamp": "2026-08-17T05:18:29.397Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:18:29.599Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:18:29.599Z",
      "func": "loadURL",
      "message": "try #0, https://x.com/{username}/likes"
    },
    {
      "timestamp": "2026-08-17T05:18:31.935Z",
      "func": "loadURL",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2026-08-17T05:18:31.935Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:18:32.137Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:18:32.137Z",
      "func": "loadURLWithRateLimit",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2026-08-17T05:18:32.137Z",
      "func": "loadURLWithRateLimit",
      "message": "checking if URL changed"
    },
    {
      "timestamp": "2026-08-17T05:18:32.138Z",
      "func": "loadURLWithRateLimit",
      "message": "UNEXPECTED, URL change to https://x.com/i/history/likes"
    }
  ],
  "currentURL": "https://x.com/i/history/likes"
}

2. indexBookmarks

Details:

{
  "error": "URL changed from https://x.com/i/bookmarks to https://x.com/i/history\n\nURLChangedError: URL changed from https://x.com/i/bookmarks to https://x.com/i/history\n    at L_ (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:277:2261)\n    at async av (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:277:22234)\n    at async Proxy.runJob (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:4640)\n    at async Proxy.run (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:8864)\n    at async E (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:10977)\n    at async de (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:722:24214)"
}

Context:

{
  "logs": [
    {
      "timestamp": "2026-08-17T05:19:47.004Z",
      "func": "runJob",
      "message": "running job indexBookmarks"
    },
    {
      "timestamp": "2026-08-17T05:19:47.013Z",
      "func": "loadBlank"
    },
    {
      "timestamp": "2026-08-17T05:19:47.014Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:19:47.216Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:19:47.274Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:19:47.475Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:19:49.481Z",
      "func": "loadURLWithRateLimit",
      "message": [
        "https://x.com/i/bookmarks",
        [],
        false
      ]
    },
    {
      "timestamp": "2026-08-17T05:19:49.485Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:19:49.686Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:19:49.686Z",
      "func": "loadURL",
      "message": "try #0, https://x.com/i/bookmarks"
    },
    {
      "timestamp": "2026-08-17T05:19:51.773Z",
      "func": "loadURL",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2026-08-17T05:19:51.774Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:19:51.974Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:19:51.975Z",
      "func": "loadURLWithRateLimit",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2026-08-17T05:19:51.975Z",
      "func": "loadURLWithRateLimit",
      "message": "checking if URL changed"
    },
    {
      "timestamp": "2026-08-17T05:19:51.976Z",
      "func": "loadURLWithRateLimit",
      "message": "UNEXPECTED, URL change to https://x.com/i/history"
    }
  ],
  "currentURL": "https://x.com/i/history"
}

3. indexConversations

Details:

{
  "error": "URL changed from https://x.com/messages to https://x.com/i/chat\n\nURLChangedError: URL changed from https://x.com/messages to https://x.com/i/chat\n    at L_ (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:277:2261)\n    at async nv (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:277:14812)\n    at async Proxy.runJob (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:4471)\n    at async Proxy.run (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:8864)\n    at async E (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:278:10977)\n    at async de (file:///usr/lib/cyd/resources/app.asar/.vite/renderer/main_window/assets/main-COPr54sM.js:722:24214)"
}

Context:

{
  "logs": [
    {
      "timestamp": "2026-08-17T05:21:10.316Z",
      "func": "runJob",
      "message": "running job indexConversations"
    },
    {
      "timestamp": "2026-08-17T05:21:10.327Z",
      "func": "loadBlank"
    },
    {
      "timestamp": "2026-08-17T05:21:10.327Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:21:10.529Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:21:10.606Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:21:10.808Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:21:12.812Z",
      "func": "loadURLWithRateLimit",
      "message": [
        "https://x.com/messages",
        [],
        false
      ]
    },
    {
      "timestamp": "2026-08-17T05:21:12.819Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:21:13.021Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:21:13.021Z",
      "func": "loadURL",
      "message": "try #0, https://x.com/messages"
    },
    {
      "timestamp": "2026-08-17T05:21:18.511Z",
      "func": "loadURL",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2026-08-17T05:21:18.511Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2026-08-17T05:21:19.090Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2026-08-17T05:21:19.090Z",
      "func": "loadURLWithRateLimit",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2026-08-17T05:21:19.090Z",
      "func": "loadURLWithRateLimit",
      "message": "checking if URL changed"
    },
    {
      "timestamp": "2026-08-17T05:21:19.092Z",
      "func": "loadURLWithRateLimit",
      "message": "UNEXPECTED, URL change to https://x.com/i/chat"
    }
  ],
  "currentURL": "https://x.com/i/chat"
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions