HP5008 (interaction-failed) means one of the custom interactions in your
config threw an error, or caused an uncaught error on the page while it ran.
Either the steps no longer match the page, or the page breaks when a user does
the same thing. Run the interaction in a headed browser to see where it fails.
| Code | HP5008 |
|---|---|
| Name | interaction-failed |
| Default severity | Error |
| Group | Interaction during hydration |
| What it means | An interaction from the config threw an error or caused a page error. |
What the HP5008 interaction failed finding means
Custom interactions are Playwright steps you add under interactions in the
config. Each one runs on the routes it matches, after hydration by default or
with the page's scripts held back (when: "before-hydration"). hydration-proof
reports the interaction by name:
"continue to payment" failed: locator.click: Timeout 30000ms exceeded.
"continue to payment" caused an error on the page: TypeError: Cannot read properties of undefined (reading 'total')Uncaught errors count only when they happen after the steps started. The page errors are listed as evidence. It is an error, because either the test or the page is broken.
Likely causes
- A selector in the steps that no longer matches, after a change to the page.
- Steps that wait for something the page never shows.
- A
before-hydrationinteraction that expects React to handle an event: while the scripts are held back, only plain HTML behavior works. - A real bug: the page throws when a user does these steps.
- The page did not hydrate, so the steps never ran; the message says so.
How to fix it
- Run the interaction in a headed browser (
--headed) to see where it fails; the command is below. - If a step fails, update the locator or the wait in the config. Locators by
role or label (
getByRole,getByLabel) survive markup changes better than CSS selectors. - If the page throws, fix the page: the finding's evidence has the error.
- If a page did not hydrate, look at that page's own findings first, such as HP9001.
npx hydration-proof test --route /checkout --headed --workers 1A step that finds its elements by label and role:
import { defineConfig } from "hydration-proof";
export default defineConfig({
interactions: [
{
route: "/checkout",
name: "continue to payment",
steps: async ({ page }) => {
await page.getByLabel("Email").fill("test@example.com");
await page.getByRole("button", { name: "Continue" }).click();
await page.getByText("Payment").waitFor();
},
},
],
});Interactions documents every field, including when and
scenarios.