The AI Was Smart. The Input Was a Cookie Banner.
A friend of mine told me he uses a tool from Google that turns blogs into podcasts. He said it was fun, so I wanted to try it. I asked Claude what the tool was, and it pointed me at NotebookLM's Audio Overview, which turns a set of sources into a two-host podcast-style conversation.
I picked a long technical article on keeping large distributed systems from collapsing under load, gave NotebookLM the URL, and a few minutes later it had generated the audio. I loaded it onto my phone and played it during a grocery pickup drive. I was looking forward to it.
Five minutes in, the hosts were not talking about the article. I was parked, waiting for the groceries to arrive, so I skipped ahead. They weren't talking about it there either. The whole 21-minute episode was about something else, and what it was about is the rest of this post.
I already had a good idea of what had gone wrong, from knowing how these systems are built. It didn't help, because I couldn't do anything about it until I was back at my computer.
The episode was about the site's cookie consent banner, and then about the error the page threw.

21 Minutes About Cookies
AI-generated audio overview, unedited
What did NotebookLM actually read?
Two things, and neither was the article.
The first was the cookie preferences wall. It lists essential, performance, functional and advertising cookie tiers, defines "cross-context behavioral advertising", warns that clearing cookies or switching devices means you have to make your selection again, and links to a separate external form for opting out of tracking by other identifiers.
The second was a pair of failures, one soft and one hard. The soft one was a banner message: "Unable to save cookie preferences, we will only store essential cookies at this time." The hard one was the page itself giving up:
Unexpected application error.
TypeError: Failed to fetch dynamically imported module:
https://example.com/assets/search-results-<hash>.js
That is the full text of the source. The hosts worked with it. They talked through the consent tiers, then the crash, and they noticed the irony on their own: a page about building resilient systems had gone down because one lazy-loaded JavaScript chunk failed to fetch. Their closing line was "The bureaucracy survives. The product dies."
Why didn't the model notice?
Because it was never shown anything that said the source was wrong.
The site is a single-page application. The server returns a nearly empty HTML shell, and the article is rendered client-side by JavaScript, split into chunks that load lazily. A browser runs that JavaScript and ends up with the article. A fetcher that reads what the server returned, without fully rendering the app the way a browser session would, ends up with the shell plus whatever text happened to be on the page: the consent banner and the error output from the failed import.
I don't think the site blocked anything. This looks like a mismatch between how the page delivers its content and how the ingestion layer reads it. I haven't confirmed which step in NotebookLM's fetcher fell short, and I'm not going to guess at its internals.
From the model's side, the task was "make an engaging podcast from this source", and the source was a document about cookies and a TypeError. Nothing in that input contradicted itself. There was no signal to react to.
Was the model bad?
No. It was handed garbage and produced a fluent, confident, well-structured 21-minute conversation about the garbage. It stayed on topic, it found the one funny connection in the material, and it kept two voices going for the full runtime. That is the problem: the output looked like a success.
I knew it was wrong five minutes in because I knew what the article was supposed to be about. A listener who didn't would have had no reason to doubt it, and might have come away believing the article was about consent management.
What had to work around the model?
Six things, and none of them did.
- Ingestion. Something has to render JavaScript, deal with consent walls, and recognize an error page as an error page. A human glances at the page and sees it failed. The pipeline treated it as content.
- Input validation. Nothing asked whether this source looked like the article it was supposed to be. Even a crude check (does the text contain the title's key terms, is it mostly boilerplate) would have caught it.
- Harness. The loop, tools, retries and guardrails that turn a model into something that finishes a task. A model cannot fix an input it cannot see, so the harness is where "fetch failed, try rendering it" has to live.
- Context engineering. Deciding what goes into the context window and in what form, and what gets stripped: navigation, banners, cookie walls, error output.
- Evals and observability. Knowing when an output is confidently wrong. A 21-minute episode with no relevance to the source is a failure that reports itself as success unless something is measuring it.
- Human judgment. I was the only validation step in this pipeline, and I was one by accident.
None of those is the model. Each is code, configuration or process that someone has to build, run and keep working, and the product is only as good as the weakest one.
Why is there so much to build around it?
Because of what people expect from software. For a long time a program did what it said it would do, and it did it the same way every time. Same input, same output, today and next month. When it broke, it broke the same way each time, so you could reproduce the failure, find the line and fix it. Users carry that expectation without thinking about it. I gave the tool a URL and expected a podcast about the article at that URL.
Once a model is part of the software, that contract changes. The model can do far more than the code it replaces. It can summarize, hold a conversation and make sense of input nobody wrote a parser for. It is also non-deterministic: the same input is not guaranteed to produce the same output, and a failure does not raise an exception. It produces plausible text. Here, every stage handed something to the next stage and the last one produced audio. Nothing in the pipeline stopped, and nothing in it was designed to notice that the audio had nothing to do with the source.
So the determinism people expect has to be supplied by everything around the model, because the model will not supply it. Inputs get checked before they go in. Outputs get checked against the source after. The system records what the model was given, so when something goes wrong there is a way to find out why. That is most of the engineering in an AI product, and it is easy to miss from the outside, where all you see is the model doing something impressive.
Is this only a problem for tools built on someone else's model?
No, and NotebookLM is not the point of this post. The same applies to the products the model makers ship themselves.
A coding assistant is not a model with a text box. Around the model there is a harness: the tools it can call, how it reads and edits files, what it is allowed to run, how it decides what to keep in context as a session grows, and what happens when a command fails or the output is too long to use. A chat product has the same shape: instructions the model is given before you type anything, search and retrieval to ground its answers, memory, rendering, and checks on what goes out. I'm describing the general structure here, not any one product's internals.
These tools exist because a model on its own is not enough to do the job. Even for the companies that train the models, the model is one component of the product, and the rest of it is what makes the model usable. It simply cannot be otherwise, for the reasons above: the model needs the right input, something has to catch it when it is confidently wrong, and a person has to be able to find out why when it happens.
Summary
- NotebookLM produced a 21-minute podcast about a cookie consent wall and a JavaScript error instead of the article I gave it.
- The cause was an ingestion mismatch. The source page is a single-page app that renders its content client-side, and the fetcher read the shell, the banner and the failed-import error.
- The model did what it was asked and did it well. Nothing in its input told it the source was wrong.
- Software used to do the same thing every time, and users still expect that. A model is more capable but non-deterministic, and its failures look like normal output.
- The product has to supply the consistency the model does not: ingestion, input validation, harness, context engineering, evals and observability.
- This is not specific to one tool. Coding assistants and chat products from the model makers are also a model plus a lot of surrounding software, and the model alone could not do their job.