diff -u b/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php --- b/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -314,8 +314,9 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL) { $form = $this->retrieveForm($form_id, $form_state); - // We don't allow to set state on GET requests. - if (!$form_state->isMethodType('GET')) { + // Persisting $form_state is a side-effect disallowed during a "safe" HTTP + // method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1). + if ($this->requestStack->getCurrentRequest()->isMethodSafe()) { $form_state->setCached(); } diff -u b/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php --- b/core/lib/Drupal/Core/Form/FormState.php +++ b/core/lib/Drupal/Core/Form/FormState.php @@ -475,9 +475,12 @@ * {@inheritdoc} */ public function setCached($cache = TRUE) { - if ($this->isMethodType('GET')) { - throw new \LogicException('Caching on GET requests is not allowed.'); + // Persisting $form_state is a side-effect disallowed during a "safe" HTTP + // method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1). + if ($cache && \Drupal::request()->isMethodSafe()) { + throw new \LogicException(sprintf('Form state caching on %s requests is not allowed.', \Drupal::request()->getMethod())); } + $this->cache = (bool) $cache; return $this; } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Form/FormStateInterface.php +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php @@ -640,6 +640,10 @@ public function getButtons(); * TRUE if the form should be cached, FALSE otherwise. * * @return $this + * + * @throws \LogicException + * If the current request is using an HTTP method that must not change + * state (e.g., GET). */ public function setCached($cache = TRUE);