halo-dev/halo · warning · Error

json.errors[0]

Error message

json.errors[0]

What it means

Client-side JS in the complete-profile flow: sendRequest() POSTs to /complete-profile/send-email-code with the CSRF header. If the response is not ok, it parses JSON and, when the body has a non-empty errors array, throws new Error(json.errors[0]) — the Error message is whatever the server put in the first element of its errors array. The thrown Error is caught and surfaced to the user by the shared sendVerificationCode() helper (common.html).

Source

Thrown at application/src/main/resources/templates/gateway_fragments/complete_profile.html:87

    document.addEventListener("DOMContentLoaded", function () {
      const headerName = /*[[${_csrf.headerName}]]*/ "";
      const token = /*[[${_csrf.token}]]*/ "";

      async function sendRequest() {
        const email = document.getElementById("email").value;
        const response = await fetch("/complete-profile/send-email-code", {
          method: "POST",
          body: JSON.stringify({ email: email }),
          headers: {
            "Content-Type": "application/json",
            [headerName]: token,
          },
        });

        if (!response.ok) {
          const json = await response.json();
          if (json.errors && json.errors.length) {
            throw new Error(json.errors[0]);
          }
          if (json.detail) {
            throw new Error(json.detail);
          }
          throw new Error(i18nResources.sendVerificationCodeFailed);
        }

        return response;
      }

      const emailCodeSendButton = document.getElementById("emailCodeSendButton");
      sendVerificationCode(emailCodeSendButton, sendRequest);
    });
  </script>
</form>

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Refresh the page to obtain a fresh CSRF token, then retry.
  2. Enter a valid, unused email before clicking send.
  3. Open DevTools -> Network and inspect the response body to read the actual errors[0] message, which states the precise rejection reason.
  4. Wait out any rate-limit window before retrying.
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the CSRF token is fresh and the email is valid before sending:
if (!email || !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) {
    showError("Enter a valid email."); return;
}
// reload the page if it has been open long enough for the CSRF token to expire

Type guard

// Narrow the server response shape before reading errors:
function hasErrorsArray(json) {
  return json != null && Array.isArray(json.errors) && json.errors.length > 0;
}

Try / catch

try {
    await sendRequest();
} catch (e) {
    // e.message === server's errors[0]
    showToast(e.message || i18nResources.sendVerificationCodeFailed);
}

Prevention

When it happens

Trigger: The email-code endpoint rejects the request and returns a body with an `errors` array — e.g. invalid email format, email already registered/owned by another account, rate limiting, or a CSRF token mismatch/expiry (the hidden _csrf token grew stale on a long-open form).

Common situations: CSRF token expired because the page sat open; email already in use; throttling on repeated sends; submitting before typing a valid email.

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/35bab31a3ed23a13. Report an issue: GitHub.