Hydration Mismatch False Positive From Cursor'S Data-Cursor-Ref Attribute
Next.js 16.3.8 with Turbopack shows a hydration error overlay when Cursor's built-in browser stamps data-cursor-ref attributes on DOM nodes. The attribute is not in server HTML or the React tree, so the mismatch is a false positive.
Cursor's browser extension (or a reproducing inline script) adds data-cursor-ref attributes to DOM nodes before React hydration. React's hydration diffing treats unexpected extra attributes as mismatches, and Next.js's error overlay reports them as hydration errors.
1. Create a fresh Next.js 16.3.8 App Router project. 2. Open app/layout.tsx and add an inline script in the body that sets data-cursor-ref on h1 and p elements during parsing (simulating Cursor). 3. Run `next dev`. 4. Open any page. 5. Observe hydration mismatch overlay where the only diff is data-cursor-ref.
Fixing Code Block
// app/layout.tsx
import type { Metadata } from 'next';
import type { ReactNode } from 'react';
export const metadata: Metadata = {
title: 'Next.js App',
};
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
if (typeof MutationObserver === 'undefined') return;
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'attributes' && mutation.attributeName === 'data-cursor-ref') {
const target = mutation.target;
if (target instanceof Element && target.hasAttribute('data-cursor-ref')) {
target.removeAttribute('data-cursor-ref');
}
} else if (mutation.type === 'childList') {
for (const node of mutation.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE) {
const element = node as Element;
if (element.hasAttribute('data-cursor-ref')) {
element.removeAttribute('data-cursor-ref');
}
element.querySelectorAll('[data-cursor-ref]').forEach((el) => el.removeAttribute('data-cursor-ref'));
}
}
}
}
});
observer.observe(document.documentElement, { attributes: true, childList: true, subtree: true });
})();
`,
}}
/>
{children}
</body>
</html>
);
}
The script installs a MutationObserver on document.documentElement to remove `data-cursor-ref` attributes from any element as soon as they are added. Since the attribute is never part of React's virtual DOM, stripping it before hydration eliminates the mismatch without affecting the application's actual rendered props.
Edge Case Audit
This is a development-only workaround for Cursor's built-in browser. It removes data-cursor-ref attributes that Cursor may rely on for DOM node addressing, potentially breaking Cursor's ability to inspect or interact with those nodes after page load. It also adds overhead for DOM mutations; if performance is a concern, condition the observer to only run in development. Rollback: delete the script block. Do not use in production because it may interfere with legitimate scripts that expect data-cursor-ref to persist.