DEV Community

shaojie gong
shaojie gong

Posted on

I fixed my scraper four times in one night. Each fix revealed a worse bug.

You know what's scarier than a crash? A feature that works 90% of the time and lies about the other 10%.

My Chrome extension saves your AI chats so you don't lose them. Someone saved a long ChatGPT conversation, and it came out missing chunks. Not the end — random pieces from the middle. Turn 3 gone, turn 5 gone, but 1, 2, 4, 6 all there. Like someone had gone through with scissors.

I'd tested this thing a dozen times. It always looked fine. Because I'd been testing with short conversations, and the bug only shows up when the chat is long enough to scroll. Fun.

Here's what was actually happening, and it's one of those things that's obvious once you know it and completely invisible until you do.

Modern chat apps use something called virtual scrolling. When a conversation gets long, the browser doesn't keep all those messages in the page at once — it'd eat too much memory. So it throws away the ones you can't see and rebuilds them when you scroll back. At any given moment, only the messages near your screen actually exist in the page. The rest are just... not there.

My extension read the page and grabbed every message it could find. Which, on a long chat, was only the handful currently on screen. The rest had been evicted. I was saving a snapshot of a peephole and calling it the whole conversation.

Okay. So I need to scroll the page myself, top to bottom, and collect messages as they get rendered. Fine. I wrote that. Put up a little overlay so the user knows why their page is suddenly scrolling on its own. Shipped it.

Saved a long chat. Still incomplete.

Turns out I was scrolling the wrong thing. I'd written the code to find the scrollable container by looking inside the page's

element — seemed reasonable. But ChatGPT's conversation scroller lives outside , in some deeply nested div with a class name that looks like a cat walked across the keyboard. So my code found nothing, fell back to scrolling the whole window, which doesn't scroll, and quietly did nothing. The overlay showed up, sat there, and collected the same peephole as before.

Fixed the container detection — scan the whole page, pick the tallest scrollable thing, skip the sidebar. Saved again.

Now it got everything! And put it in completely the wrong order.

Because when you hit save, your page is usually scrolled to the bottom. So my code collected the last few messages first, then jumped to the top and worked down. I was storing them in the order I discovered them, not the order they were written. The conversation read like someone shuffled a deck.

So I thought, easy, I'll sort by each message's position in the page after I'm done. Except — and this is the part that made me laugh out loud at midnight — by the time I finish scrolling, the messages I collected at the top have been evicted again. The very virtual scrolling I was fighting had deleted the elements I wanted to sort. Trying to sort them was like arranging furniture that had already been thrown out.

The fix that finally worked: record each message's absolute vertical position the instant I collect it, while the element is still alive. Just a number. Then sort by the number at the end. Nodes can vanish all they want; the number stays.

That did it. Full conversation, correct order, from a chat long enough to need four screens of scrolling.

Four attempts. Each one "fixed" it and revealed the next thing underneath. Peephole → wrong scroller → wrong order → sorting ghosts. I don't think I could've reasoned my way to the last bug from the start; I had to walk into each one.

A few things I'm taking away:

  • "It works on my machine" is doing a lot of heavy lifting when your test data is three messages long. Test with the ugly, realistic, oversized input.
  • Virtual scrolling is everywhere now, and if you scrape any modern app, it will quietly lie to you about what's on the page.
  • Fixing a bug that reveals a deeper bug isn't failure. It's just how the layers come off.

Still 0 users, still $0. But it saves the whole conversation now, in the right order, which two days ago it absolutely did not.

If you scrape pages for a living: what's the sneakiest data-loss bug you've hit? I feel like everyone who does this has one.

— building NotebookBloom in public, #3

Top comments (0)