# Troubleshoot Wicket

> What each Wicket widget message means, and what to do when the widget is missing, a token is refused, test keys reach production or a visitor cannot pass.

Source: https://www.coritan.com/docs/wicket/troubleshooting/

The widget's **Help** link opens this page. Start with what you see, find it below, and follow the fix. The browser's console says more than the widget does: open it with <kbd>F12</kbd> and look for lines that start with `Wicket:`.

## The widget does not appear

The page shows an empty space where the widget should be, or no widget at all. Work down the list.

### The page's hostname is not on the widget's list {#hostname-not-listed}

Our host then tells the browser to refuse the frame, so the widget cannot show a message of its own. The console shows `Framing 'https://wicket.coritan.com/' violates the following Content Security Policy directive: "frame-ancestors ..."`, and after ten seconds a line that starts `Wicket: the frame for site key ... has not loaded`. Add the page's hostname to the widget's hostnames. A hostname covers every name under it, so `example.com` covers `www.example.com`, and `www.example.com` does not cover `example.com`. A page on `localhost` is never covered: use a [test key](/docs/wicket/test-keys/) there.

### Your page's Content-Security-Policy blocks the script or the frame

The console shows `Refused to load the script` or `Refused to frame`. Add Wicket's address to `script-src` and `frame-src`:

```text
script-src https://wicket.coritan.com;
frame-src https://wicket.coritan.com;
```

If your policy sets `default-src` and no `frame-src`, name the address in `default-src` or add a `frame-src`. [Add Wicket to your site](/docs/wicket/add-wicket-to-your-site/#allow-wicket-in-a-content-security-policy) has the details.

### The page is open as a file

A page you open from your disk, with an address that starts `file://`, has no http or https address, so Wicket cannot tell which site is asking and does not run the check, even with a test key. The console shows this warning:

```text
Wicket: this page has no http or https address (it is open as a file, for example), so the Wicket host will not show the widget here. Serve it from your site, or from localhost with a test key.
```

Serve the page from a local web server, so that its address starts `http://localhost`, and use a [test key](/docs/wicket/test-keys/). A real widget cannot list `localhost` ([Hostnames](/docs/wicket/#hostnames)).

### The script did not run

Check that the script tag's address is `https://wicket.coritan.com/v1/api.js`, that the browser's network panel shows it loaded, and that an ad or privacy blocker is not removing it. With `?render=explicit` in the address, nothing is drawn until your code calls `wicket.render()`.

### The container is wrong

The container needs the class `wicket-widget` for implicit rendering, and a `data-sitekey`. Without a site key the console says `the widget has no site key`.

### The widget is invisible, or its appearance is `interaction-only`

These draw nothing until they must ([Widget modes](/docs/wicket/widget-modes/)). Use a [test key](/docs/wicket/test-keys/) that shows a box, such as `wk_test_interactive`, to see a visible widget.

## The widget says This site's check is not set up for this page {#site-not-set-up}

The widget shows a warning, the line above, and a code in small type. The code says which of three problems it is. The console names the site key and what to fix.

`unknown_sitekey`
: No widget has this site key, or the container has none. Copy the site key from the widget in the dashboard again. A key that starts `wks_` is a secret key, and a page must never hold one: the script refuses it and draws no widget.

`widget_disabled`
: Our team turned the widget off. The dashboard says why above the widget's tabs, and its **Contact support** button starts a conversation ([Contact support](/docs/support/conversations/)). A form that uses the widget stops passing checks until our team turns it back on.

`hostname_not_allowed`
: The page's hostname is not on the widget's list. Add it, as in [the first problem above](#the-widget-does-not-appear). The browser usually refuses the frame first, so you see an empty space and not this message.

## The widget says Could not reach Wicket

The warning shows **Could not reach Wicket. Check your connection** and a **Try again** button. The error code is `network`, `rate_limited` or `internal`, and the script starts the check again by itself every 8 seconds, up to five times, unless `retry` is `never`.

- For `network`, check the visitor's connection, and that no firewall, proxy or blocker stops requests to `wicket.coritan.com`.
- For `rate_limited`, the visitor's network started too many checks in a minute ([Wicket limits](/docs/wicket/limits/#rate-budgets)). It clears by itself. A test script that loads many widgets from one address meets it first.
- For `internal`, try again in a moment. If it keeps happening, [contact support](/docs/support/conversations/) with the time and the site key.

## The widget says We could not check this browser

The check refused the visitor: the error code is `failed`. Wicket refuses only on near-certain evidence, such as a browser that says a script is driving it, and the widget never says which. The visitor has a **Try again** button, and a link **Having trouble?** in the widget's footer.

If the visitor is a person, see [A visitor cannot pass](#a-visitor-cannot-pass). If you are testing, remember that a script, a headless browser or a test runner is what Wicket is built to refuse. Use a [test key](/docs/wicket/test-keys/) in tests, not a real widget.

## The widget says This browser cannot run the check

The error code is `unsupported`, and your `unsupported-callback` is called. The check needs three things in the visitor's browser: JavaScript, Web Workers and WebCrypto. The cause is usually one of these:

- The page is served over plain `http://`. A browser gives a frame WebCrypto only when the page that holds it is served over HTTPS, or from `localhost`. Serve the page over HTTPS.
- The browser is very old, or a privacy setting or an extension turns off Web Workers or WebCrypto. Ask the visitor to update the browser or to try another one.

The script writes the reason once for each widget as a console warning: `Wicket: this browser cannot run the check. It needs Web Workers and WebCrypto, and a page served over plain http (not localhost) does not get them. Serve the page over HTTPS.` Your `unsupported-callback` can return `true` to say you handled it, and the script then writes nothing ([Widget options](/docs/wicket/widget-options/#callbacks)).

## The widget says This check expired or Time ran out

A token works once and for 300 seconds. When it expires the widget shows **This check expired**, and with `refresh-expired` at `auto` it starts a new check at once, so the visitor usually sees it for a moment. A box that nobody ticks for 120 seconds shows **Time ran out**, and `refresh-timeout` decides whether the check starts again by itself or waits for a click on **Check again**.

If a visitor leaves a form open for a long time and then sends it, your server may meet an expired token. Read the next section.

## Your server says the token is not valid

The verify call answers `"success": false` with a code in `error-codes` ([Verify a token on your server](/docs/wicket/verify-tokens/)). What each code means in practice:

`missing-input-response`
: Your server got no token. The container must be inside the `<form>`, or your script must copy the token into the request. Check the field's name: it is `wicket-response` unless `data-response-field-name` changed it. A form sent before the visitor passed has no token.

`timeout-or-duplicate`
: The token is older than 300 seconds, or your server verified it before. Verify each token once, in one place: not in the browser and again on the server, and not twice for one form. After a submit that fails, call `wicket.reset()` for a new token, because the old one is spent whether or not your form accepted it.

`invalid-input-response`
: The token cannot be opened, or it belongs to another widget. Check that the site key on the page and the secret key on the server are from the same widget. A test token (`WICKET.DUMMY.TOKEN`) also gets this answer from a real secret key: see [Test keys in production](#test-keys-in-production).

`invalid-input-secret`
: No widget has this secret key. It may have a typo, have been [rotated](/docs/wicket/widget-settings/#rotate-the-secret-key), or belong to a widget our team turned off. Copy the secret key from where you stored it. We show it only once, so rotate it if you have lost it.

`bad-request`
: We could not read the request. Send `secret` and `response` as form fields, multipart fields or JSON, and keep the token under 2048 characters.

The `hostname` in a passing answer is the hostname of the page that showed the widget. Compare it with the hostname you expect, so a token made on another of your sites is not accepted by mistake.

## Test keys in production

A test site key makes the widget pass in any browser, and its token is the fixed text `WICKET.DUMMY.TOKEN`. A real secret key refuses that token with `invalid-input-response`, so a page that went live with a test site key cannot pass any form. Replace `wk_test_...` with the widget's real site key.

The mistake can also run the other way. A test secret key accepts every token, including a real one and a forged one, so a server that went live with `wks_test_pass` accepts every form. Keep the keys in your server's settings by environment, and check on the real hostname that a form with no token is refused. The keys and what each does are on the [test keys](/docs/wicket/test-keys/) page.

## A visitor cannot pass

A visitor sees **We could not check this browser**, even though they are a person.

Wicket never shows a puzzle, a picture or a sound, and it refuses a visitor only on near-certain evidence. Doubt costs a visitor a click or a little more waiting. A visitor on a VPN or a privacy browser may be asked to tick a box. Ticking it with a keyboard or a screen reader never counts against a visitor.

Ask the visitor to:

1. Select **Try again**.
2. Turn off extensions that block scripts or change what the browser reports, and reload the page.
3. Update the browser, or try another one.
4. Select **Having trouble?** and describe what they were doing.

**Having trouble?** opens a short form in the widget with one optional field, **What were you doing?**, and a **Send** button. It sends the visitor's note to Wicket together with a reference to the check, and the widget answers **Thanks. We will look at it.** It never says whether the visitor was taken for a bot, because that answer would help a script. The link is there only after a failed check, and `feedback-enabled` set to `false` takes it away.

You can send the same kind of report from your server when you learn that a check was a person or a bot: [Verify a token on your server](/docs/wicket/verify-tokens/).

## What the console lines mean

Every line the script writes starts with `Wicket:`. The ones about a problem on your page are below, with what to change.

| The line says | What to change |
| --- | --- |
| `render: the widget has no site key. Add data-sitekey to the container or pass sitekey.` | Give the container a `data-sitekey`, or pass `sitekey` to `wicket.render`. Your `error-callback` receives `unknown_sitekey`. |
| `render: this is a secret key, which never goes on a page. Use the site key that starts with wk_.` | Put the widget's site key in the page, and [rotate the secret key](/docs/wicket/widget-settings/#rotate-the-secret-key) if it was ever public. The widget is not drawn. |
| `render: the container ... was not found` | The element or selector you passed to `wicket.render` is not on the page yet. Call it after the element exists. |
| `execute: no widget for ...` | The reference you passed to `wicket.execute` is not a widget on the page. Render the widget first. |
| `the loader could not read its own address, so it cannot find the Wicket host. Load it from <host>/v1/api.js.` | Load the script from its own address with a `<script src>` tag. Do not copy its code into another file. |
| `this page has no http or https address ...` | [The page is open as a file](#the-page-is-open-as-a-file). |
| `unknown_sitekey for site key ...`, `hostname_not_allowed for site key ...` or `widget_disabled for site key ...` | [The widget says This site's check is not set up for this page](#site-not-set-up). |
| `the frame for site key ... has not loaded after 10 seconds ...` | [The page's hostname is not on the widget's list](#hostname-not-listed), or your Content-Security-Policy blocks the frame. |
| `this browser cannot run the check ...` | [The widget says This browser cannot run the check](#the-widget-says-this-browser-cannot-run-the-check). |
| `the widget with site key ... is invisible, so the page moved when it loaded ...` | Add `data-appearance="interaction-only"` to the container of an Invisible widget, and give it no `min-height` ([Invisible widgets](/docs/wicket/add-wicket-to-your-site/#invisible-widgets)). |
| `... is not valid and was ignored ...` or `callback names ..., which is not a function on window.` | Correct the option ([Invalid values](/docs/wicket/widget-options/#invalid-values)). |

## Related

- [How Wicket works](/docs/wicket/how-wicket-works/)
- [Add Wicket to your site](/docs/wicket/add-wicket-to-your-site/)
- [Widget options](/docs/wicket/widget-options/)
- [Verify a token on your server](/docs/wicket/verify-tokens/)
- [Test keys](/docs/wicket/test-keys/)
