Technical postmortem from July 14, 2026. Everything that follows is documented in Chromium bug 534655509.
Update, August 19, 2026. The conclusion of this postmortem was wrong, so we are correcting it right here at the top. The crash was not a remote experiment that Google switched off that afternoon: it is still alive. We reproduced it again on stable Chrome 150.0.7871.187 on July 28 and on 151.0.7922.138 on August 19, with their memory dumps. We also know what actually triggers it, and it is narrower than we thought: it takes three things at once, a router that navigates by swapping the DOM (here, Astro's ClientRouter) and both ways of registering WebMCP tools living on the same page, the imperative one and the declarative one. With only one of the two, it doesn't crash. That is why WebMCP is switched back on at kiwop.com, with its three tools registered the imperative way. Below is the original July 14 account, with the bisection corrected: two of its four steps were wrong.
On the morning of July 14, any visitor to kiwop.com running Chrome 150 who clicked a link watched the tab die: an "Aw, Snap!" screen and an error code, RESULT_CODE_KILLED_BAD_MESSAGE. The homepage loaded fine. Every page loaded fine if you landed on it via a direct URL. It only broke on navigation. Four hours later the bug vanished without us touching a single line, and that's the most interesting part of the story.
This is the account of how we cornered the crash all the way to Chromium's source code, why the most likely cause wasn't in our site, and what we learned about building with experimental APIs in production.
What We Had Enabled: WebMCP
WebMCP is Chrome's experimental API that lets a website register tools for AI agents: you expose functions with document.modelContext.registerTool(), and an agent (a browser extension, an assistant) can discover and execute them instead of wrestling with your interface through simulated clicks.
We had it enabled through the official origin trial (Chrome 149 through 156), with the token in a meta tag on every page. Two imperative tools and one declarative tool on the chat form. It's part of our bet on agentic browsing: agents being able to operate a website is the next step after being able to cite it.
On Chrome 149, everything worked. When Chrome 150 hit stable, the trouble started.
A Crash the Health Checks Can't See
The insidious part of the failure is that all our monitoring was green. The synthetic checks request URLs and every single one returned 200. The site was "healthy" for any watchdog robot and broken for any human navigating it, because the crash only triggered on same-site navigation initiated by a click, the kind that reuses Chrome's render process.
First operational lesson, one we've already turned into internal policy: after a significant change, walk the site with real clicks in a real browser. A 200 doesn't say the site works, it says the server responds.
The Bisection: Six Steps to Corner It
In a development environment we reproduced the crash and started removing pieces, one at a time. That first table, the one from that morning, told us the crash survived even with zero tools registered, and that is where the remote experiment hypothesis came from. It was measurement noise. Repeated calmly on July 28 and revalidated on August 19, the real bisection is this one:
- Navigation router, imperative tools and declarative tool, all at once: crash.
- The same tools, but no router (plain old classic navigation): no crash.
- Router and only the imperative tools: no crash.
- Router and only the declarative tool: no crash.
- Origin trial active with zero tools registered (
getTools()returns an empty list): no crash. - No origin trial token (the API doesn't even exist on the page): navigation works perfectly.
The conclusion, different from July's, is that having the API active is not enough: the failure needs a specific combination. And that is the good news, because a combination can be broken up. That morning we disabled WebMCP in production and the site returned to normal immediately, which was the urgent part.
Here's the second lesson: the token lived in an environment variable, so disabling the feature took minutes. Had it been hardcoded into the templates, the site would have stayed broken while we raced to patch code under pressure. Every experimental API in production needs a kill switch.
What the Chromium Source Code Says
With the fire out, we dug in. The first surprise: nobody had reported this crash. Not on the Chromium tracker, not in the spec's repository, not on Stack Overflow. As far as we could tell, we were the first to see it.
The second: the origin trial was untouched in Chrome 150. The official Chrome Platform Status entry confirms the 149 to 156 milestone range with no changes. The only thing that changed in 150 was the API surface: navigator.modelContext was deprecated in favor of document.modelContext.
The third, and here's the crux of it: we compared the WebMCP code between the Chrome 149 and 150 branches, and it's identical. The origin trial gating, the bindings, all of it. The regression wasn't in WebMCP's code.
What we did find is the exact mechanism of the error. In Chrome's browser process, the file model_context_user_data.cc tracks WebMCP's state document by document. If the render process and the browser process disagree about whether WebMCP is enabled for a given document, the browser process interprets the render's message as illegal IPC and kills it. That kill is literally the RESULT_CODE_KILLED_BAD_MESSAGE we were seeing on screen. And it wasn't the first time this family of bugs had bitten: a CL from May 2026 fixed a crash identical in mechanics, where the render believed WebMCP was active and the browser process hadn't gotten the memo.
The Twist That Threw Us Off: The Bug Vanished Without Us Touching Anything
In the afternoon we tried to reproduce the crash on a clean Chrome profile, with the exact same build (150.0.7871.115). No luck. We tried eight configurations, including an exact replica of the incident: the same site, the same token, navigation with real clicks. Nothing.
And a few hours later it no longer reproduced even in the browser that had been crashing all morning. Same build, same profile, same site, same token. Nothing had changed on our end whatsoever.
When a 100% reproducible failure disappears with zero changes on the client, the explanation that's left lives on the server side. Chrome turns features on and off live through Finch, its remote experimentation system: Google can flip on a variant for a percentage of installs and revert it with a kill switch within hours, without shipping a browser update. Our working hypothesis, and the one we've reported, is that a WebMCP-related experiment was enabled that morning, conflicted with the origin trial's per-document state, and someone at Google hit the kill switch after seeing the crashes. We can't see this from the outside; Google can check it against their variations history in a minute, and that's exactly what we asked for in the report.
For the record, in the interest of honesty: this is a hypothesis. What is fact is the timeline, the nine memory dumps the crashes left in the local Crashpad directory, which we kept as evidence, and that the bug died on its own.
And the hypothesis fell apart. On July 28 we put the token back in our development environment and the very first click on the menu killed the tab again, on stable Chrome 150, with no experiment in sight. On August 19 it happened again on Chrome 151. What had disappeared that afternoon in July was not the bug: it was our ability to reproduce it. The minimal test pages we built had no navigation router, and without that piece the crash never shows up. The real site did have one, and that is where the tab kept dying.
What We Learned, in Case You're Building with Experimental APIs
- An origin trial puts Google inside your runtime. The feature can change under your feet without you shipping anything. Design for it: experimental code gets isolated and gets a way to turn it off.
- A kill switch, or nothing. An environment variable, a remote flag, whatever it takes to disable the feature in minutes without touching templates.
- Health checks can't see navigation breakage. After every serious change, real clicks in a real browser. No exceptions.
- Bisect one variable at a time. Our table is what turns "my site is broken" into a report a Chromium engineer can act on.
- Keep the minidumps. Chrome's Crashpad directory is the accident's black box: that morning's dumps are the only physical evidence left of the incident.
The Report, and What Happens Now
The full case is in bug 534655509, with the public reproduction pages we built for the Chromium team. Google still hasn't reproduced the failure, and now we know why: they tested our minimal repro, which is a classic site with no navigation router, exactly the missing piece.
WebMCP has been switched back on at kiwop.com since August 19, 2026: three tools registered the imperative way, none declarative, and the site walked click by click before calling anything good.
In the meantime, the underlying lesson doesn't change: the agentic web arrives with young APIs, remote experiments, and errors that no classic monitor catches. It's new ground, and it's exactly where we work. If you want your site ready for agents without gambling on navigation along the way, start with an AI audit or get in touch.
Frequently Asked Questions
What is WebMCP?
WebMCP is an experimental Chrome API, driven by Google and Microsoft at the W3C, that lets a web page register tools for AI agents through document.modelContext.registerTool(). As of July 2026, it's in origin trial in Chrome from version 149 through 156, with a stable rollout planned for 157.
What does Chrome's RESULT_CODE_KILLED_BAD_MESSAGE error mean?
It means Chrome's browser process has deliberately killed a tab's render process for sending it an IPC message it considers illegal or malformed. It isn't a render hang: it's a defensive kill, meant to stop compromised processes in their tracks. The user sees it as an "Aw, Snap!" screen.
What is Finch, Chrome's experimentation system?
Finch is Google's mechanism for turning Chrome features on or off remotely, by percentage of installs and without shipping an update. Every Chrome instance periodically downloads a "seed" of experiments that decides which variants are active. It enables gradual rollouts as well as kill switches: reverting a feature causing problems within hours.
Is it risky to enable an origin trial in production?
It's manageable if you treat it for what it is: experimental code whose behavior can change without you doing anything. The three rules that work for us are isolating the feature behind a switch that disables it in minutes, verifying the site by actually navigating it after every Chrome version change, and monitoring navigation flows too, not just response codes.