I'm not entirely sure if this goes in the Thymeleaf project or the Spring Boot project. Spring Boot 2.5.4 Custom ErrorController

The template I have contains a number of large tables. At a certain point in the template, if I encounter an Exception I am no longer redirected to the Error Page I created. Instead, my Error Page is embedded inline with the partially rendered template. If I move me error back a few lines in the template, the Error Page displays as expected.

Here's my ErrorController

package com.csi.smartspooler.controllers;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.util.HtmlUtils;

import lombok.RequiredArgsConstructor;

@Controller
@RequiredArgsConstructor
public class MainErrorController implements ErrorController //
{
  private static final Logger LOG = LogManager.getFormatterLogger();
  private final BaseController base;

  @RequestMapping("/error")
  public String error(final HttpServletRequest request, final Model model) {
    LOG.debug("handling error");
    Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
    Integer statusCode = status == null ? -1
        : Integer.valueOf(status.toString());
    Object errorMessageObj = request
        .getAttribute(RequestDispatcher.ERROR_MESSAGE);

    Exception exception = (Exception) request
        .getAttribute("javax.servlet.error.exception");

    List<String> allErrors = new ArrayList<>();
    String errsList = "";
    if (exception != null) {
      allErrors = getAllErrors(exception);
      for (String err : allErrors) {
        LOG.error("err [%s]", err);
        errsList += "<br>" + HtmlUtils.htmlEscape(err);
      }
      LOG.error(exception);
    }

    String errorMessage = statusCode == HttpStatus.NOT_FOUND.value()
        ? "Not Found"
        : (errorMessageObj == null ? "Unknown" : errorMessageObj.toString());

    errorMessage = exception == null ? errorMessage
        : String.format("%s<br>%s%s", //
            (errorMessage == null || "".equals(errorMessage)) ? ""
                : (errorMessage), //
            exception.getClass().getName(), //
            errsList);

    Object requestURI = request
        .getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
    Object requestQueryString = request
        .getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);

    Enumeration<String> attNames = request.getAttributeNames();
    while (attNames.hasMoreElements()) {
      String attName = attNames.nextElement();
      Object attValue = request.getAttribute(attName);
      LOG.debug(String.format("%s : '%s'", attName, attValue));
    }
    String requestedUrl = String.format("%s%s", requestURI,
        (requestQueryString == null ? "" : ("?" + requestQueryString)));
    LOG.error(String.format("requestedUrl %s, statusCode %s, errorMessage %s",
        requestedUrl, statusCode, errorMessage));

    model.addAttribute("requestedUrl", requestedUrl);
    model.addAttribute("statusCode", statusCode);
    model.addAttribute("errorMessage", errorMessage);
    model.addAttribute("myVersion", base.versionService.getVersion());
    model.addAttribute("title", "Error");
    model.addAttribute("user", base.getUser());

    return "error";
  }

  private List<String> getAllErrors(final Throwable exception) {
    List<String> allErrors = new ArrayList<>();
    allErrors.add(exception.getMessage());
    Throwable cause = exception.getCause();
    if (cause != null) {
      List<String> errors = getAllErrors(cause);
      for (String error : errors) {
        if (!allErrors.contains(error)) {
          allErrors.add(error);
        }
      }
    }
    return allErrors;
  }
}

Here's my error template

<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport"
    content="width=device-width, initial-scale=1, shrink-to-fit=no">

<title th:text="'SmartSpooler Configuration v' + ${smartspoolerVersion}"></title>
<link th:replace="fragments :: ss-Header" />
</head>

<body>

    <main role="main" class="container ss-Fill">

        <div th:replace="fragments :: ss-Navbar"></div>

        <h3>Error Page</h3>
        <div>
            Requested URL: <b th:text=${requestedURL}></b>
        </div>
        <div>
            Status code: <b th:text=${statusCode}></b>
        </div>
        <div>
            Error Message: <b th:utext=${errorMessage}></b>
        </div>

    </main>

    <div th:replace="fragments :: ss-Footer"></div>

</body>
</html>

Here's the template with the error introduced to exercise this issue.

<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
  th:object="${lineConfig}">
<head>
<meta charset="utf-8">
<meta name="viewport"
  content="width=device-width, initial-scale=1, shrink-to-fit=no">

<title th:text="${title}"></title>
<link th:replace="fragments :: ss-Header" />
</head>

<body>

  <main role="main" class="ss-Fill">


    <div th:replace="fragments :: ss-Navbar"></div>

    <div
      th:replace="${sessionService.getAndRemoveAttribute('updated')} ? ~{fragments :: ss-Updated} : _"></div>

    <div
      th:replace="${#fields.hasAnyErrors()} ? ~{fragments :: ss-Errors} : _"></div>

    <form action="#" th:action="@{/lineconfig}"
      th:object="${lineConfig}" method="POST" id="myForm">

      <input name="uuid" type="hidden" th:field="*{uuid}" />


      <div class="bg-dark text-white"
        style="padding-left: 8px; font-size: 1.5em;">Line
        Parameters</div>

      <table class="table table-striped table-sm"
        style="table-layout: fixed; word-wrap: break-word;">

        <thead class="thead-dark">
          <tr>
            <th scope="col" style="width: 25%">&nbsp;</th>
            <th scope="col" style="width: 25%">Current</th>
            <th scope="col" style="width: 50%">New</th>
          </tr>
        </thead>

        <tbody>

          <tr
            th:replace="fragments :: ss-ReadOnlyEnum(
              title='Line Number',
              fieldName='lineNumber',  
              origConfig=${origConfig})"></tr>
          <tr
            th:replace="fragments :: ss-ReadOnlyEnum(
              title='MCCI Port',
              fieldName='mcciPort',  
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-ReadOnlyText(
              title='Source Filename',
              fieldName='sourceFilename',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.lineType()}, 
              title='Line Type', 
              fieldName='lineType', 
              formFields=${#fields}, 
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-Input(
              title='Transmit Channel ID',
              fieldName='transmitChannelId',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-Input(
              title='Receive Channel ID',
              fieldName='receiveChannelId',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-Input(
              title='TCP Port (1-65535)',
              fieldName='tcpPort',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-Input(
              title='FDMP Block Size (64-1024)',
              fieldName='fdmpBlockSize',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-Checkbox(
              title='Line Enabled',
              fieldName='lineEnabled',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-Checkbox(
              title='Loopback',
              fieldName='loopback',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.charSet()}, 
              title='Character Set', 
              fieldName='serialCharacterSet', 
              formFields=${#fields}, 
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.baudRate()}, 
              title='Baud Rate',
              fieldName='serialBaudRate',               
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.parity()}, 
              title='Parity',
              fieldName='serialParity', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.dataBits()}, 
              title='Data Bits',
              fieldName='serialDataBits', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.stopBits()}, 
              title='Stop Bits',
              fieldName='serialStopBits', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.replacementCharacter()}, 
              title='Parity Replacement Character',
              fieldName='parityReplacementChar', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.replacementCharacter()}, 
              title='Buffer Overrun Replacement Character',
              fieldName='bufferOverrunReplacementChar', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.replacementCharacter()}, 
              title='Framing Error Replacement Character',
              fieldName='framingErrorReplacementChar', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

ERROR INTRODUCED HERE <!--  
          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.clockSource()}, 
              title='Clock Source',
              fieldName='clockSource', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.polarity()}, 
              title='Clock Polarity',
              fieldName='clockPolarity', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.polarity()}, 
              title='Data Polarity',
              fieldName='dataPolarity', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.polarity()}, 
              title='DTR/CD Polarity',
              fieldName='dtrCdPolarity', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          <tr
            th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.polarity()}, 
              title='RTS/CTS Polarity',
              fieldName='rtsCtsPolarity', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

        </tbody>
      </table>

      <div class="table-responsive">

        <div class="bg-dark text-white"
          style="padding-left: 8px; font-size: 1.5em;">Parser
          Parameters</div>

        <table class="table table-striped table-sm"
          style="table-layout: fixed; word-wrap: break-word;">

          <thead class="thead-dark">
            <tr>
              <th scope="col" style="width: 25%">&nbsp;</th>
              <th scope="col" style="width: 25%">Current</th>
              <th scope="col" style="width: 50%">New</th>
            </tr>
          </thead>

          <tbody>

            <tr
              th:replace="fragments :: ss-ListSingleSelect(
              title='Parser Name',
              fieldName='parserName', 
              listSelections=${parserNamesList},
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Parser Timeout (0-60 secs)',
              fieldName='parserTimeout',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Parser Max Size (1-6160 kilobytes)',
              fieldName='parserMaxSize',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>


            <tr
              th:replace="fragments :: ss-Input(
              title='Parser Max Unresolved Size (bytes)',
              fieldName='maxUnresolvedSize',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          </tbody>
        </table>
      </div>

      <div class="table-responsive">

        <div class="bg-dark text-white"
          style="padding-left: 8px; font-size: 1.5em;">Wrapping
          Parameters</div>

        <table class="table table-striped table-sm"
          style="table-layout: fixed; word-wrap: break-word;">

          <thead class="thead-dark">
            <tr>
              <th scope="col" style="width: 25%">&nbsp;</th>
              <th scope="col" style="width: 25%">Current</th>
              <th scope="col" style="width: 50%">New</th>
            </tr>
          </thead>

          <tbody>

            <tr
              th:replace="fragments :: ss-Input(
              title='LMF', fieldName='wrappingLMF',
              formFields=${#fields}, origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.classification()}, 
              title='Classification',
              fieldName='wrappingClassification', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-ReadOnlyText(
              title='Classification Prosign',
              fieldName='wrappingClassificationProsign',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='CIC',
              fieldName='wrappingCIC',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Subject',
              fieldName='wrappingSubject',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Account Code',
              fieldName='wrappingAccountCode',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='OPS Signals',
              fieldName='wrappingOpsSignals',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='OSRI',
              fieldName='wrappingOSRI',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='TRC',
              fieldName='wrappingTRC',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='From PLA',
              fieldName='wrappingFromPLA',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='DSRIs',
              fieldName='wrappingDSRIs',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='ALTRI',
              fieldName='wrappingALTRI',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Security Words',
              fieldName='wrappingSecurityWords',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='XMT PLAs',
              fieldName='wrappingXmtPLAs',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Action PLAs',
              fieldName='wrappingActionPLAs',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-Input(
              title='Info PLAs',
              fieldName='wrappingInfoPLAs',
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='Action Precedence',
              fieldName='wrappingActionPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-NullableEnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='Info Precedence',
              fieldName='wrappingInfoPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='CCOMS High Action Precedence',
              fieldName='wrappingCCOMSHighActionPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-NullableEnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='CCOMS High Info Precedence',
              fieldName='wrappingCCOMSHighInfoPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='CCOMS Normal Action Precedence',
              fieldName='wrappingCCOMSNormalActionPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-NullableEnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='CCOMS Normal Info Precedence',
              fieldName='wrappingCCOMSNormalInfoPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='ID High Action Precedence',
              fieldName='wrappingIDHighActionPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-NullableEnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='ID High Info Precedence',
              fieldName='wrappingIDHighInfoPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-EnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='ID Normal Action Precedence',
              fieldName='wrappingIDNormalActionPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

            <tr
              th:replace="fragments :: ss-NullableEnumSingleSelect(
              values=${@domainService.precedence()}, 
              title='ID Normal Info Precedence',
              fieldName='wrappingIDNormalInfoPrecedence', 
              formFields=${#fields},
              origConfig=${origConfig})"></tr>

          </tbody>
        </table>
      </div>

      <span th:replace="fragments :: ss-Buttons"></span>

    </form>

  </main>

  <div th:replace="fragments :: ss-Footer"></div>

  <script th:replace="fragments :: ss-FormScripts"></script>


</body>
</html>

And finally here's the fragments template


<!--  FRAGMENT :: ss-Header -->
<div th:fragment="ss-Header" th:remove="tag">
  <link rel="icon" href="/favicon.ico" type="image/x-icon" />
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
  <link rel="stylesheet"
    href="webjars/bootstrap/4.3.1/css/bootstrap.min.css" />
  <link rel="stylesheet" href="ssWeb.css" />
</div>


<!-- FRAGMENT :: ss-Header -->
<div th:fragment="ss-Navbar" class="bg-dark ss-Fill"
  style="display: inline-block; clear: right;">

  <div class="bg-dark">

    <div class="float-left">
      <h3 style="margin-left: 10px; margin-top: 5px;"
        class="bg-dark text-white" th:text="${title}">REPLACE -
        TITLE</h3>
    </div>

    <div class="float-right" style="margin-right: 10px;">
      <p>
        <a th:unless="${hideHomeLink}"
          style="font-size: 1em; margin-top: 1px;"
          class="float-right text-white" href="/">Main Menu</a> <a
          th:if="${hideHomeLink}"
          style="opacity: 0; font-size: 1em; margin-top: 1px;"
          class="float-right text-white text-decoration-none" href="/">&nbsp;</a>
      </p>
      <p class="mb-0 float-right text-white"
        style="font-size: 0.7em; margin-top: 3px; padding-bottom: 3px;"
        th:text="'v-' + ${myVersion}">REPLACE - VERSION</p>
    </div>

  </div>
</div>


<!-- FRAGMENT :: ss-Updated -->
<h4 th:fragment="ss-Updated" class="text-success ss-Fill"
  style="display: inline-block; clear: right; text-align: center;">SUCCESSFULLY
  UPDATED</h4>


<!-- FRAGMENT :: ss-Errors -->
<h4 th:fragment="ss-Errors" class="text-danger ss-Fill"
  style="display: inline-block; clear: right; text-align: center;">--
  PLEASE FIX ERRORS --</h4>


<!-- FRAGMENT :: ss-NullableEnumSingleSelect -->
<tr
  th:fragment="ss-NullableEnumSingleSelect (values, title, fieldName, formFields, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>
  <td>
    <div
      th:style="${origConfig.__${fieldName}__} == null ? 'font-weight: bold;' : _"
      th:text="${origConfig.__${fieldName}__} == null ? '-- NOT CONFIGURED --' : ${origConfig.__${fieldName}__.getDisplayValue()}">REPLACE
      - CURRENT VALUE</div>
  </td>
  <td><select
    th:classappend="${formFields.hasErrors('__${fieldName}__')} ? 'is-invalid' : _"
    th:id="${fieldName}" class="ss-singleSelect ss-W90 form-control"
    th:field="*{__${fieldName}__}">
      <option value="">-- NOT CONFIGURED --</option>
      <option th:each="enum : ${values}" th:value="${enum}"
        th:text="${enum.displayValue}"></option>
  </select> 
  <!--/* ERRORS */-->
    <div th:if="${formFields.hasErrors('__${fieldName}__')}"
      style="clear: left;" class="text-danger float-left"
      th:errors="*{__${fieldName}__}"></div></td>
</tr>


<!-- FRAGMENT :: ss-EnumSingleSelect -->
<tr
  th:fragment="ss-EnumSingleSelect (values, title, fieldName, formFields, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>
  <td>
    <div
      th:style="${origConfig.__${fieldName}__} == null ? 'font-weight: bold;' : _"
      th:text="${origConfig.__${fieldName}__} == null ? '-- NOT CONFIGURED --' : ${origConfig.__${fieldName}__.getDisplayValue()}">REPLACE
      - CURRENT VALUE</div>
  </td>
  <td><select th:id="${fieldName}"
    class="ss-singleSelect ss-W90 form-control"
    th:field="*{__${fieldName}__}">
      <option th:each="enum : ${values}" th:value="${enum}"
        th:text="${enum.displayValue}"></option>
  </select></td>
</tr>

<!-- FRAGMENT :: ss-ListSingleSelect -->
<tr
  th:fragment="ss-ListSingleSelect (title, fieldName, listSelections, formFields, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>
  <td>
    <div th:text="${origConfig.__${fieldName}__}">REPLACE -
      CURRENT VALUE</div>
  </td>
  <td><select th:id="${fieldName}"
    class="ss-singleSelect ss-W90 form-control"
    th:field="*{__${fieldName}__}">
      <option th:each="listSelection : ${listSelections}"
        th:value="${listSelection}" th:text="${listSelection}"></option>
  </select></td>
</tr>


<!-- FRAGMENT :: ss-Input -->
<tr th:fragment="ss-Input (title, fieldName, formFields, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>

  <td>
    <div
      th:style="${origConfig.__${fieldName}__} == null ? 'font-weight: bold;' : _"
      th:text="${origConfig.__${fieldName}__} == null ? '-- NOT CONFIGURED --' : ${origConfig.__${fieldName}__}">REPLACE
      - CURRENT VALUE</div>
  </td>

  <td><input
    th:classappend="${formFields.hasErrors('__${fieldName}__')} ? 'is-invalid' : _"
    class="ss-W90 form-control" type="text"
    th:field="*{__${fieldName}__}" /> 
    <!--/* ERRORS */-->
    <div th:if="${formFields.hasErrors('__${fieldName}__')}"
      style="clear: left;" class="text-danger float-left"
      th:errors="*{__${fieldName}__}"></div></td>

</tr>


<!-- FRAGMENT :: ss-Checkbox -->
<tr th:fragment="ss-Checkbox (title, fieldName, formFields, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>
  <td>
    <div th:text="${origConfig.__${fieldName}__.booleanValue()} ? 'YES' : 'NO'">REPLACE
      - CURRENT VALUE</div>
  </td>
  <td><div>
      <input class="ss-Checkbox" th:name="${fieldName}" th:id="${fieldName}" 
        type="checkbox" th:checked="*{__${fieldName}__.booleanValue()}" />
    </div></td>
</tr>


<!-- FRAGMENT :: ss-ReadOnlyText -->
<tr
  th:fragment="ss-ReadOnlyText (title, fieldName, formFields, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>
  <td>
    <div th:text="${origConfig.__${fieldName}__}">REPLACE -
      CURRENT VALUE</div>
  </td>
  <td>NOT EDITABLE <input type="hidden"
    th:field="*{__${fieldName}__}" />
  </td>
</tr>

<!-- FRAGMENT :: ss-ReadOnlyEnum -->
<tr
  th:fragment="ss-ReadOnlyEnum (title, fieldName, origConfig)">
  <th scope="row">
    <div th:text="${title}">REPLACE - TITLE</div>
  </th>

  <td>
    <div th:text="${origConfig.__${fieldName}__.getDisplayValue()}">REPLACE
      - CURRENT VALUE</div>
  </td>

  <td>NOT EDITABLE <input type="hidden"
    th:field="*{__${fieldName}__}" /></td>
</tr>

<!-- FRAGMENT :: ss-Buttons -->
<span th:fragment="ss-Buttons" th:remove="tag">
  <hr> <a type="submit" href="#"
  onclick="document.getElementById('myForm').submit()"
  style="width: 100px; margin: 4px 2px; cursor: default;"
  class="btn btn-primary" role="button">Submit</a> <a
  style="width: 100px; margin: 4px 2px; cursor: default;"
  th:href="${session.resetURL}" class="btn btn-primary" role="button">Reset</a>
</span>


<!-- FRAGMENT :: ss-Footer -->
<div th:fragment="ss-Footer" th:remove="tag">
  <script type="text/javascript"
    src="webjars/jquery/3.4.1/jquery.min.js"></script>
  <script type="text/javascript"
    src="webjars/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</div>

<!-- FRAGMENT :: ss-FormScripts -->
<script th:fragment="ss-FormScripts" type="text/javascript">
    document.onkeypress = keyPress;
    function keyPress(e) {
        var x = e || window.event;
        var key = (x.keyCode || x.which);
        if (key == 13 || key == 3) {
            tagName = document.activeElement.tagName;
            console.log(tagName);
            if (tagName != 'TEXTAREA') {
                document.getElementById('myForm').submit();
            }
        }
    }
</script>

Comment From: philwebb

I suspect this is a buffering issue where a flush has occurred before the exception happens. You could try adding spring.thymeleaf.servlet.produce-partial-output-while-processing=false to your application.properties to see if that solves the problem.

If that doesn't work, please provide a sample application as a GitHub project or a zip file so we can debug things.

Comment From: mdwheaton

Yep, that was it. Looks like I need to read these default options much more carefully. Thank you!

On Fri, Aug 27, 2021 at 5:25 PM Phil Webb @.***> wrote:

I suspect this is a buffering issue where a flush has occurred before the exception happens. You could try adding spring.thymeleaf.servlet.produce-partial-output-while-processing=false to your application.properties to see if that solves the problem.

If that doesn't work, please provide a sample application as a GitHub project or a zip file so we can debug things.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-boot/issues/27828#issuecomment-907507123, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAP2IZZYIF5J4AHZUJTSSFTT7AGHNANCNFSM5C6IBFSA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

Comment From: mdwheaton

Yep, that was it. Looks like I need to read these default options much more carefully.