Skip to the content
Documentation
Manuals

"This form has expired": form token refusals

This page is for site owners who see "form expired" pages or warnings, and for developers who handle them.

  • Topic type: Concept
  • For: Visitors Editors
  • doc.features.6-0.form-expired-page
  • Last changed
  • JSON
On this page

This page is for site owners who see "form expired" pages or warnings, and for developers who handle them. Exponential protects every form against cross-site request forgery with a form token (the ezformtoken extension in the kernel). When a POST arrives without its token, or with a wrong one, the visitor used to see a 500 page, and the log recorded "Unexpected error" for what is really a refusal. Since 27 September 2026 the answer is a clear page with the right status.

What a visitor sees

A page that says, in plain words:

  • the form has expired: the page was open for a long time, or the form was sent from another page;
  • nothing was saved;
  • Reload the form and send it again, or go to the front page (the dashboard in the administration).

A signed-out visitor is told they may have to sign in again; when the refused form was itself a sign-in form, the page asks to sign in again. The wording is the same for a missing and a wrong token, and does not talk about security tokens and sessions.

The page is design:error/kernel/6.tpl, shipped in design/standard; the admin designs fall back to it. Check:

ls design/*/templates/error/kernel/6.tpl

While a design has no such template, or it renders empty because the template cache was built before it existed, a built-in explanation is shown.

What the browser and scripts get

Value
HTTP status403 Forbidden (kernel error 6, mapped in error.ini)
HeadersCache-Control: no-store, the configured security headers
HTML requestKernel error 6 through the error module, inside the pagelayout of the module that was posted to; no redirect; session and posted data are left as they are
XHR, Accept: application/jsonA JSON body with the same message
Error view title and path"Form expired" instead of "kernel (6)"

In the log, a refusal writes one line to var/log/warning.log with the check (missing or wrong), the method, the path and the siteaccess, never a token. The same refusal again (same check, siteaccess, path and client) within RefusalLogCollapseSeconds is counted instead of written, and the next line gives the count.

Settings

FileBlockKeyDefaultMeaning
settings/site.iniHTMLFormsRefusalLogCollapseSeconds60Collapse window for repeated refusals. 0 writes every one
settings/site.iniHTMLFormsSecretplaceholder textCSRF secret. Set your own per project
settings/error.iniErrorSettings-kernelHTTPError[6]403Status of the refusal

For developers

  • ezpFormTokenException carries the failed check and code 403. The old code threw a plain Exception that nothing caught until the uncaught handler.
  • ezpFormTokenRefusal builds the answer: status, headers, the template parameters of design:error/kernel/6.tpl (reason, reason_code, referrer, retry_url, is_ajax, title, message, action), the JSON body and the built-in page.
  • The web kernel catches the exception at request/input. A refusal escaping anywhere else (the REST or tree menu kernel, a module running the check itself, the uncaught exception handler) gets the same 403 and warning line.
  • The built-in strings are literal ezpI18n calls in the contexts kernel/error/formtoken and design/standard/error/formtoken, translated into German and eng-US. An unmatched refusal no longer writes an http_response_code() has no effect warning.
  • A page carrying a form token is marked Cache-Control: private, no-cache, must-revalidate, so no shared cache can store it with a token and hand it to an anonymous visitor.

Become an Exponential Partner. Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster. Start with Partners: start here and How to apply.

Was this helpful?

Only your answer is kept, not who you are.

Something wrong on this page? Report an error