Skip to content

Make logic more resilient, and only send actionable error reports #610

@micahflee

Description

@micahflee

We routinely get error report emails that we can't actually do anything about. This leads to alert fatigue. We should only get alerts related to bugs we can actually fix. For certain errors we can maybe make the app more resilient, and for others we can maybe make it display an error message to the user without submitting a report.

It probably makes sense to fix this one error type at a time, starting with the most frequent. We should actually look up our historical error reports to help with this.

But just looking at what came in recently, there are a bunch of x_runJob_indexMessages_Timeout errors. Here is an example of one:

TimeoutError: Timeout waiting for selector: div[data-testid="DmActivityContainer"]
    at Proxy.waitForSelector (file:///Applications/Cyd.app/Contents/Resources/app-x64.asar/.vite/renderer/main_window/assets/main-CnYKz77U.js:132:22112)
    at async Proxy.runJobIndexMessages (file:///Applications/Cyd.app/Contents/Resources/app-x64.asar/.vite/renderer/main_window/assets/main-CnYKz77U.js:329:818)
    at async Proxy.runJob (file:///Applications/Cyd.app/Contents/Resources/app-x64.asar/.vite/renderer/main_window/assets/main-CnYKz77U.js:333:20709)
    at async Proxy.run (file:///Applications/Cyd.app/Contents/Resources/app-x64.asar/.vite/renderer/main_window/assets/main-CnYKz77U.js:366:392)
    at async I (file:///Applications/Cyd.app/Contents/Resources/app-x64.asar/.vite/renderer/main_window/assets/main-CnYKz77U.js:383:61408)
    at async K (file:///Applications/Cyd.app/Contents/Resources/app-x64.asar/.vite/renderer/main_window/assets/main-CnYKz77U.js:383:64292)

The error report includes this screenshot:

Image

Here's the (redacted) sensitive context info:

{
  "logs": [
    {
      "timestamp": "2025-11-26T19:34:10.256Z",
      "func": "loadURL",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2025-11-26T19:34:10.257Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2025-11-26T19:34:11.122Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2025-11-26T19:34:11.123Z",
      "func": "loadURLWithRateLimit",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2025-11-26T19:34:11.123Z",
      "func": "loadURLWithRateLimit",
      "message": "checking if URL changed"
    },
    {
      "timestamp": "2025-11-26T19:34:11.124Z",
      "func": "loadURLWithRateLimit",
      "message": "finished loading URL"
    },
    {
      "timestamp": "2025-11-26T19:34:59.372Z",
      "func": "runJobIndexMessages",
      "message": [
        "selector never appeared",
        {
          "name": "TimeoutError"
        }
      ]
    },
    {
      "timestamp": "2025-11-26T19:34:59.375Z",
      "func": "runJobIndexMessages",
      "message": [
        "loading conversation and waiting for messages failed, try #",
        1
      ]
    },
    {
      "timestamp": "2025-11-26T19:35:01.121Z",
      "func": "loadURLWithRateLimit",
      "message": [
        "https://x.com/messages/REDACTED",
        [],
        false
      ]
    },
    {
      "timestamp": "2025-11-26T19:35:01.123Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2025-11-26T19:35:04.240Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2025-11-26T19:35:04.240Z",
      "func": "loadURL",
      "message": "try #0, https://x.com/messages/REDACTED"
    },
    {
      "timestamp": "2025-11-26T19:35:06.059Z",
      "func": "loadURL",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2025-11-26T19:35:06.059Z",
      "func": "waitForLoadingToFinish",
      "message": "waiting for loading to finish"
    },
    {
      "timestamp": "2025-11-26T19:35:07.122Z",
      "func": "waitForLoadingToFinish",
      "message": "loading finished"
    },
    {
      "timestamp": "2025-11-26T19:35:07.123Z",
      "func": "loadURLWithRateLimit",
      "message": "URL loaded successfully"
    },
    {
      "timestamp": "2025-11-26T19:35:07.123Z",
      "func": "loadURLWithRateLimit",
      "message": "checking if URL changed"
    },
    {
      "timestamp": "2025-11-26T19:35:07.125Z",
      "func": "loadURLWithRateLimit",
      "message": "finished loading URL"
    },
    {
      "timestamp": "2025-11-26T19:35:57.150Z",
      "func": "runJobIndexMessages",
      "message": [
        "selector never appeared",
        {
          "name": "TimeoutError"
        }
      ]
    },
    {
      "timestamp": "2025-11-26T19:35:57.157Z",
      "func": "runJobIndexMessages",
      "message": [
        "loading conversation and waiting for messages failed, try #",
        2
      ]
    }
  ],
  "currentURL": "https://x.com/messages/REDACTED"
}

Reading this, Cyd did the follow:

  • loaded a DM conversation at a URL like https://x.com/messages/REDACTED (but the X website never actually loaded, just shows the X logo like in the screenshot)
  • waited for div[data-testid="DmActivityContainer"] to appear, but it timed out
  • loaded the URL again, waited for the div again, failed again
  • loaded the URL again, waited for the div again, failed again
  • threw an error, which the user reported

I don't think there's anything we can do with this error report. It's also really tricky to figure out how to fix this, since it's clearly an intermittent issue on X's side that we can't exactly write tests for very easily. Potential solutions though are:

  • when trying again, wait longer, like 60 seconds instead of whatever it is now
  • if we fail on this after trying 3 times, don't fallback to an error report, but instead display an error message telling the user something is wrong on X's side and to try again later

I think we should systematically do this for every error report type we get until we basically stop receiving error reports, except for ones that are genuinely bugs -- like catching when X's API changes again or something.

Metadata

Metadata

Assignees

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