Turnstile throws error "missing-input-response"

I have been trying unsuccessfully to get turnstile captcha working in a simple contact form (wanting to avoid the nonstop crush of comment spam).

  • On form submission, I get a message “Captcha failed for this form, please try again”.
  • In the log I see Form Turnstile invalid: [/contact] {"success":false,"error-codes":["missing-input-response"],"messages":[]}

As for my site:

  • My Grav installation is up to date.
  • I have the turnstile keys in the /user/config/plugins/form.yaml file as instructed in the docs.
  • The form is very similar to the example in the docs.
  • The theme’s form template uses the “raw” filter (content|raw) - though it fails with or without “raw”.
  • I’ve set “Include externals in JS pipeline” to false.

Does anyone have an idea what “missing-input-response” means and/or what I may be missing? Are the docs still up to date?

1 Like

I was getting a load of spam on my site which was using Google’s reCAPTCHA, so I decided to try Cloudflare’s Turnstile in an attempt to reduce the volume of spam.

I was getting the exact same error message in the log (“missing-input-response”).

On inspecting the source of the page I realised that the Turnstile script was not being referenced.

Using the JS link provided on this page I added it to my theme template as follows:

    {% block head %}
      {% block javascripts %}
        {% do assets.addJs('https://challenges.cloudflare.com/turnstile/v0/api.js', {'priority':130, 'loading': 'defer'}) %}
      {% endblock %}
      {{ assets.js() }}
    {% endblock head %}

And straight away my Turnstile captcha started working:


Not sure if this is going to help you, but thought I’d share my experience anyway!


Although the Form plugin will load the javascript of Turnstile, Turnstile might not be happy if you have set js_pipeline: true

The setting mentioned by @Wartybliggens should work (at least it works in my test):

  js_pipeline_include_externals: false

Problem solved:

The docs say “You can ignore the script tag suggested, as Grav takes care of it for you” – but that was not happening in my case, because I use a theme that’s a copy of antimatter (the default theme) which I customized, so it doesn’t get updates. Turns out that themes implement the entire head, and the head in the current version of antimatter has differences that affect script loading.

So in one sense, it was my fault: my theme was a bit out of date. But this kind of rubs me the wrong way. The docs say “Grav takes care of it for you” but any theme can easily break the mechanism that would support that claim, including all the out-of-date themes that are still available it seems. Architecturally, Grav can’t both be html-agnostic and also guarantee things that depend on the html being a certain way, at least not without making it clear in the docs. In general I’m curious whether an approach that would have Grav build the head and have it be configurable would solve for this sort of thing and still work for users of Grav, rather than letting themes break it.

In any case, thank you @christhorn and @pamtbaau for your help! It’s working now.

1 Like


Out of 116 themes, there are about 51 themes that match regex {%\s*block\s.*\sdeferred \s*%} somewhere in their code. Which means 65 themes do not use deferred, which might lead to your issue. Thirty of these themes are updated after the introduction of the feature.

IMHO, it is a responsibility of the authors of themes/plugins to keep an eye on the changelog of Grav and update their themes/plugins accordingly.

However, there is also a responsibility of the team (with the help of the community perhaps) to keep an eye on themes/plugins that might cause issues. See this discussion on Github: Theme/plugin repository cleanup and quality control

You might consider creating a PR on the docs and alter the remark into:
“You can ignore the script tag suggested, as Grav takes care of it for you when the theme loads scripts in a deferred block.”

1 Like