Troubleshooting
"Provider not found" Error
Symptom: useConsentManager must be used within a ConsentManagerProvider error.
Fix: Ensure the component calling useConsentManager() (or any c15t hook) is rendered inside a ConsentManagerProvider:
// Wrong — hook is outside the provider
function App() {
const { consents } = useConsentManager(); // throws
return <ConsentManagerProvider options={...}>...</ConsentManagerProvider>;
}
// Correct — hook is inside the provider
function App() {
return (
<ConsentManagerProvider options={...}>
<MyComponent /> {/* useConsentManager works here */}
</ConsentManagerProvider>
);
}Banner Doesn't Show
Possible causes:
-
Opt-out jurisdiction — In CCPA/opt-out regions, the banner is not shown because tracking is allowed by default. Check
modelfromuseConsentManager()— if it's'opt-out', the banner is intentionally hidden. -
Consent already given — If the user has already made a consent choice, the banner won't reappear. Clear cookies or use
resetConsents()to test again. -
activeUIis'none'— Something is explicitly settingactiveUIto'none'. Check the DevTools panel for the current consent state. -
Backend not responding — In
'c15t'mode, the banner waits for the backend/initresponse. Check the Network tab for failed requests to yourbackendURL.
// Debug: check what the consent manager sees
const { activeUI, model, isLoadingConsentInfo } = useConsentManager();
console.log({ activeUI, model, isLoadingConsentInfo });Consent Not Persisting
Symptom: Consent is lost after page reload.
Possible causes:
-
Incognito/private mode — Some browsers restrict cookie storage in private browsing.
-
Cookie settings — In
'offline'mode, consent is stored in cookies. Ensure cookies are not being blocked by browser settings or extensions. -
Different domains — Cookies are domain-scoped. If your dev server uses a different domain than production, consent won't carry over.
-
Backend errors — In
'c15t'mode, check that the backend is saving consent successfully. Enabledebug: truein provider options to see detailed logs.
Scripts Not Loading
Symptom: Third-party scripts configured in the scripts option don't load after consent is granted.
Checklist:
-
Wrong category name — The
categoryon the script must match one of theconsentCategoriesnames. For example,'measurement'not'analytics'. -
Consent condition not met — Use
has('measurement')to verify the category is actually consented. -
Script error — Check the browser DevTools Console for script loading errors. The
onErrorcallback can help debug:
{
id: 'analytics',
src: 'https://...',
category: 'measurement',
onError: ({ error }) => console.error('Script failed:', error),
}- Ad blocker — Browser extensions may block the script regardless of consent. The
anonymizeIdoption (default:true) helps avoid pattern-based blocking.
SSR Hydration Mismatch
Symptom: React hydration warnings, consent banner flashes briefly, or consent state differs between server and client.
Fixes:
- Missing
ssrData— Ensure you're passing the SSR data Promise to the provider:
<ConsentManagerProvider
options={{
mode: 'hosted',
backendURL: '...',
ssrData: fetchSSRData({ backendURL: '...', headers }),
}}
>-
Stale cache — If using a CDN or caching layer, ensure the SSR data is fresh per-request and not shared across users.
-
Debug with
useSSRStatus— Check if SSR data was actually consumed:
const { ssrDataUsed, ssrSkippedReason } = useSSRStatus();See Server-Side Utilities for full SSR setup.
TypeScript Errors
Common import issues:
// Components and hooks — main entry point
import { ConsentManagerProvider, useConsentManager } from '@c15t/react';
// Server utilities — separate entry point
import { fetchSSRData } from '@c15t/react/server';
// Headless (hooks only, no components)
import { useConsentManager } from '@c15t/react/headless';If you see type errors after updating, try:
rm -rf node_modules/.cache
bun installStill Stuck?
- Enable
debug: truein provider options for verbose console logging - Use the DevTools panel to inspect live consent state
- Check the GitHub issues for known bugs