Svelte Verify and troubleshoot
Troubleshooting
The build or dev server fails fetching the manifest
Check. vite build and vite dev download the policy through the
consentManifest plugin in vite.config.ts. vite build stops with an
error that starts with @c15t/svelte/vite: could not fetch the consent manifest, and vite dev logs it as a warning. The part in parentheses names
the cause:
| Error | Cause |
|---|---|
/manifest responded 404 | The backend URL is wrong, or still the https://your-project.inth.app placeholder. |
no backend URL is set | Neither the backendURL option nor VITE_C15T_BACKEND_URL (or VITE_INTH_PROJECT_URL) is set, or it is empty. vite build stops; vite dev warns. |
skipped the consent manifest fetch (a notice) | The backend URL is relative. With onBuildError: 'fail', this is the error build-time manifests require an absolute upstream URL. |
/manifest returned an invalid consent manifest. | The URL answers, but not with a c15t v3 manifest. |
fetch failed or no response within 10 seconds | The machine running the command cannot reach the backend. |
Fix. Set VITE_C15T_BACKEND_URL (or VITE_INTH_PROJECT_URL) to your
project's absolute backend URL where the command runs, in .env or the CI environment, and make sure that
machine can reach the backend. To deploy while it is down, build with
C15T_ON_BUILD_ERROR=runtime.
The browser fetches the manifest at runtime
Check. With manifest(), the browser requests <backendURL>/manifest on
page load instead of resolving from a bundled policy. The build had no policy
to bundle: consentManifest is missing from plugins in vite.config.ts,
the fetch failed in vite dev or in a build with
C15T_ON_BUILD_ERROR=runtime, or the backend URL is relative. Without the
plugin and without a backendURL option, manifest() has no backend URL at
all and throws when it runs.
Fix. Add the plugin or fix the cause from the
fetch errors, then
restart vite dev or rebuild. A build fetches once, and vite dev fetches
the first time the app loads the policy.
Consent requests go to the wrong backend
Check. Look at VITE_C15T_BACKEND_URL and VITE_INTH_PROJECT_URL in
.env, .env.local and the build environment, and at any backendURL in vite.config.ts or
src/App.svelte. One still has the demo project, the placeholder
https://your-project.inth.app, or a URL from another project. Vite writes
VITE_C15T_BACKEND_URL into the bundle at build time, so changing it later
does nothing until you rebuild.
Fix. Set VITE_C15T_BACKEND_URL (or VITE_INTH_PROJECT_URL) to your
Inth project's backend URL, including any path prefix, and rebuild. The project must also list your app's
origin as trusted.
The banner appears after the page
Check. In a Svelte app without a server, the browser resolves the policy after the page loads, then shows the banner. That is expected. Optional categories stay denied until the policy resolves.
Fix. For a banner in the first HTML, the page has to be server-rendered; SvelteKit does that. See choose your setup.
Why is there no banner?
Check. Read getConsentManager().policyRule.prompt and .location, or open
DevTools. In the Network panel, find the /init request.
Fix. Work through these causes in order:
- The policy asks for no prompt. Visitors in regions without a consent law, and opt-out policies with no prompt, get no banner. See why the banner may be absent.
- A choice is already stored. Clear site data for your origin, or use the DevTools panel, and reload.
- The backend request failed. A CORS error means your site's origin is not in the Inth project's trusted origins. A 404 means the backend URL is wrong. While the request fails, optional categories stay denied and no banner shows.
- The component is outside the provider.
ConsentBannermust render insideConsentProvider; outside it, Svelte throwsc15t: no v3 consent context.
Svelte throws "no v3 consent context"
Check. A getter or component ran without a ConsentProvider above
it.
Fix. Move it inside the provider.
Check. Look for a getter called in an event handler or effect. Getters use
Svelte's getContext.
Fix. Call getters at the top level of a component's <script>.
Check. If the provider is there, check that the app resolves one copy of
@c15t/svelte. Two copies create two separate contexts.
Fix. Make the app resolve a single copy of @c15t/svelte.
Theme colors are ignored
Check. The provider's theme prop applies slot styles and consentActions
only. Colors, radius, typography and other tokens in theme are not turned
into CSS in the browser, and in development the provider logs a warning about
it.
Fix. Set the --c15t-* variables on :root in a stylesheet, or render
generateThemeCSS() output as <style id="c15t-theme">. The customize page
shows both.
Check. If your values still lose, inspect the element. A generated theme
uses :root:root, so it beats your own :root rule.
Fix. Write your rule on :root:root too, or move the value into the theme.
The dialog or banner has no styles
Check. Look in <head> for <style data-c15t-styles> elements, and in
the console for a Content Security Policy error. On a server-rendered
SvelteKit page, check that src/hooks.server.ts exports c15tHandle.
Fix.
- No c15t
<style>element: the provider setsstyles={false}ornoStyle. Withstyles={false}, import@c15t/svelte/styles.cssonce, in the component that renders the provider or in your global stylesheet. - The SvelteKit banner is unstyled until hydration: add
c15tHandlefrom@c15t/svelte/kittosrc/hooks.server.ts, or setstyles={false}and import@c15t/svelte/styles.css. - The console reports a blocked inline style: pass the provider a
nonce, or setstyles={false}and import the stylesheet. The Content Security Policy page covers both. - IAB TCF surfaces are unstyled with automatic styles disabled: import
@c15t/svelte/styles.cssand@c15t/svelte/iab/styles.csstogether. With automatic styles enabled, check the policy and IAB configuration, the provider'snoStyleoption, and CSP errors.
A vendor loads before consent, or twice
Check. The vendor is still loaded some other way: a <script> tag in
index.html or app.html, a tag manager, or an SDK import in your code. Check
the Network panel with site data cleared; nothing from the vendor should load
before you allow its category.
Fix. Remove the other loader and keep only the scripts registration.
The page reloads after saving
Check. When a save withdraws a category that was granted, the provider reloads the page so code that already ran is gone. This is expected.
Fix. Set reloadOnConsentRevoked: false on the provider only if every
registered vendor stops itself through its consent API.
Names from an earlier alpha are missing
Check. An import from an earlier v3 alpha fails, such as
ConsentManagerProvider, Frame or consentManifest({ outputFile }).
@c15t/svelte was not public in v2, so the alphas renamed these with no
alias.
Fix. Use the current names:
| Removed | Use instead |
|---|---|
ConsentManagerProvider | ConsentProvider |
Frame | ConsentGate |
hosted({ url }) | hosted() with VITE_C15T_BACKEND_URL, or hosted({ backendURL }) |
ConsentManifestOptions, consentManifest({ outputFile }) | Removed. consentManifest() serves the snapshot as c15t/generated. |
More help
Troubleshoot consent covers problems shared by every framework, such as a missing banner, analytics that load before a choice, imports that fail because npm installed c15t v2, choices that disappear on reload, server HTML that differs from the browser, static builds that fail and content blockers that hide the consent UI. Verify consent lists the checks to run before release.