Vue Verify and troubleshoot
Troubleshooting
Vite fails to pre-bundle c15t's .vue files
Check. vite dev reports an error from dependency optimization for a
.vue file under @c15t/vue, or manifest() throws c15t: manifest() has no backend URL. consentManifest() is missing from the plugins array of
vite.config.ts.
Fix. Add consentManifest() from c15t/vue/vite to the plugins array,
next to @vitejs/plugin-vue, and set VITE_C15T_BACKEND_URL (or
VITE_INTH_PROJECT_URL). See the
quickstart.
app.use() throws "pass mode"
Check. The plugin options have no mode. Earlier v3 alphas took
backendURL, manifest, manifestURL and manifestSnapshot on the plugin.
Fix. Pass mode: manifest(), hosted() or offline() from
c15t/vue/vue-plugin. Move backendURL into the mode, such as
hosted({ backendURL }), or let consentManifest() supply it.
Why does the build fail to download the manifest?
Check. vite build stops with an error from consentManifest that
starts with the plugin's name, such as
@c15t/core/build: could not fetch the consent manifest from <url> during the build. The name is @c15t/core/build for c15t/build and @c15t/vue/vite
for c15t/vue/vite. vite dev logs the same message as a warning and keeps
going. The part in parentheses names the cause:
| Message | Cause | Fix |
|---|---|---|
fetch failed, with ENOTFOUND, ECONNREFUSED or another network error | The build cannot reach the backend | Build where the backend is reachable |
no response within 10 seconds | The backend did not answer in time | Check the backend, or build where it is reachable |
/manifest responded 404 | The URL is not your project's backend, such as the https://your-project.inth.app placeholder or a URL missing its path prefix | Copy the backend URL exactly as Inth shows it, or set VITE_C15T_BACKEND_URL |
/manifest returned an invalid consent manifest. | The URL answered with something other than a consent manifest, such as an HTML page | Point backendURL at the backend itself, not your site or a dashboard page |
A failed download never reuses an old snapshot. To deploy while the backend
is down, run the build with C15T_ON_BUILD_ERROR=runtime. snapshot is then
undefined, and the browser fetches the policy from the backend at runtime.
Only a build that uses manifest() downloads the manifest. The plugin
fetches after Vite has dropped the code the app does not use, so a hosted()
or offline() build never contacts the backend and never fails this way.
An error or warning that says no backend URL is set means the plugin found
no backendURL option and no variable. Set VITE_C15T_BACKEND_URL (or
VITE_INTH_PROJECT_URL) in .env or the build environment, or pass the absolute backend URL from your Inth
project. The troubleshooting guide
lists every message.
A notice that the build skipped the consent manifest fetch means the backend
URL is relative, such as /api/c15t. Pass the absolute backend URL instead.
With onBuildError: 'fail', this stops the build with build-time manifests require an absolute upstream URL.
Why is snapshot undefined?
Check. snapshot from c15t/generated is undefined, and the browser
requests ${backendURL}/manifest on page load.
Fix. snapshot is undefined when Vite has no policy to serve:
consentManifestis missing frompluginsinvite.config.ts. Without the plugin,c15t/generatedstill resolves, but exportsundefined.- The fetch failed in
vite dev, or in a build withC15T_ON_BUILD_ERROR=runtime. The terminal shows acould not fetch the consent manifestwarning. - The backend URL is relative, so the plugin skipped the fetch.
consentManifest({ source: 'runtime' })is set, so the plugin never fetches.
Fix the cause, then restart vite dev or rebuild. The plugin fetches once
when Vite starts.
app.use() fails or does nothing
Check. Look at where you import the plugin. c15t/vue is the Nuxt module
and is not a Vue plugin.
Fix. Import the plugin from c15t/vue/vue-plugin.
A composable throws "Kernel not found"
Check. The component is outside the app that installed c15tVue, for
example in a separate createApp() instance, or the composable ran outside
setup.
Fix. Install the plugin on the app that renders the component, and call
composables inside setup.
Why is there no banner?
Check. DevTools shows the
matched policy. With hosted(), find the /init request in the Network tab;
with manifest({ source: 'runtime' }), the /manifest request.
Fix. Work through these causes in order:
- The visitor's policy asks for no banner. A policy with prompt
noneshows no banner, which is common in opt-out regions. See why the banner may be absent. manifest()resolves the unknown-location policy. WithoutinputsorgeoURL, every visitor gets the policy your project assigns when the location is unknown. Check that rule, then rebuild.ConsentRootis inside a route that unmounts. Put it in the root component.- The backend did not answer. With
hosted(),/initmust return 200; with a runtime manifest,/manifestmust. A CORS error means your site's origin is missing from the Inth project's trusted origins. While resolution fails, c15t shows no UI and keeps every optional category denied. - A stored choice exists. Clear the
c15tcookie and localStorage entry, or use a private window.
The app throws IABUnavailableError
Check. The error has the code C15T_IAB_UNAVAILABLE and reads
"c15t: this visitor's policy uses IAB TCF, but iab is not set." The
visitor's policy uses the iab model and the backend sent its vendor list,
but the plugin has no iab option, or has iab: false or
iab: { enabled: false }. The standard banner does not handle the IAB model,
so c15t throws rather than leave the visitor with no consent UI.
app.use() throws when the policy arrives with prefetch; otherwise the
error is uncaught once the policy resolves, and ConsentRoot renders
nothing.
Fix. If the site uses IAB TCF, pass iab to the plugin, such as
app.use(c15tVue, { iab: {} }). See IAB TCF.
If it does not, remove the iab model from the policy for that region in
your Inth project or policy pack. A backend that answers gvl: null turns
IAB off for that request, and nothing throws.
Tokens in my CSS do not apply
Check. The c15tVue plugin appends a <style id="c15t-css-vars"> element to
<head> when you install it. The element sets every token, including the
defaults. A :root rule in your stylesheet for the same variable competes
with it on source order, so it may lose.
Fix. Set values through the plugin's tokens option. See
customize.
A script loads twice, or before consent
Check. Look for the vendor in both the plugin's scripts and a
createScriptLoader call.
Fix. Keep only scripts.
Check. Look for the vendor's own snippet in index.html, or SDK
initialization in your code.
Fix. Remove it so c15t is the only loader.
The page flashes without the banner on a server-rendered Vue app
Check. c15t does not support server rendering for plain Vue.
Fix. Use the c15t Nuxt module. See server rendering without Nuxt.
Names from an earlier alpha are missing
Check. An import or component from an earlier v3 alpha fails to resolve,
such as c15t/vue/consent-root, ConsentPreferencesLink or the default
export of c15t/vue/vite. The v3 alphas removed names that never shipped in
a stable release, with no alias.
Fix. Use the current names:
| Removed | Use instead |
|---|---|
Vue plugin options backendURL, manifest, manifestSnapshot, manifestURL, customFetch, domain | mode, a factory from c15t/vue/vue-plugin that takes them |
The default c15tVue export of c15t/vue/vite | consentManifest from c15t/vue/vite. The Vue app plugin keeps the name c15tVue. |
c15t/vue/consent-root, c15t/vue/consent-widget | Named exports from c15t/vue/vue-plugin |
ConsentPreferencesLink, runtime/components/consent-preferences-link.vue | ConsentDialogLink, consent-dialog-link.vue |
ConsentFrame | ConsentGate |
hosted({ url }) | hosted({ backendURL }), or VITE_C15T_BACKEND_URL |
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.