{"record":{"id":"35bab31a3ed23a13","repo":"halo-dev/halo","slug":"json-errors-0","errorCode":null,"errorMessage":"json.errors[0]","messagePattern":"json\\.errors\\[0\\]","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"application/src/main/resources/templates/gateway_fragments/complete_profile.html","lineNumber":87,"sourceCode":"    document.addEventListener(\"DOMContentLoaded\", function () {\n      const headerName = /*[[${_csrf.headerName}]]*/ \"\";\n      const token = /*[[${_csrf.token}]]*/ \"\";\n\n      async function sendRequest() {\n        const email = document.getElementById(\"email\").value;\n        const response = await fetch(\"/complete-profile/send-email-code\", {\n          method: \"POST\",\n          body: JSON.stringify({ email: email }),\n          headers: {\n            \"Content-Type\": \"application/json\",\n            [headerName]: token,\n          },\n        });\n\n        if (!response.ok) {\n          const json = await response.json();\n          if (json.errors && json.errors.length) {\n            throw new Error(json.errors[0]);\n          }\n          if (json.detail) {\n            throw new Error(json.detail);\n          }\n          throw new Error(i18nResources.sendVerificationCodeFailed);\n        }\n\n        return response;\n      }\n\n      const emailCodeSendButton = document.getElementById(\"emailCodeSendButton\");\n      sendVerificationCode(emailCodeSendButton, sendRequest);\n    });\n  </script>\n</form>\n","sourceCodeStart":69,"sourceCodeEnd":103,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/resources/templates/gateway_fragments/complete_profile.html#L69-L103","documentation":"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).","triggerScenarios":"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).","commonSituations":"CSRF token expired because the page sat open; email already in use; throttling on repeated sends; submitting before typing a valid email.","solutions":["Refresh the page to obtain a fresh CSRF token, then retry.","Enter a valid, unused email before clicking send.","Open DevTools -> Network and inspect the response body to read the actual errors[0] message, which states the precise rejection reason.","Wait out any rate-limit window before retrying."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Ensure the CSRF token is fresh and the email is valid before sending:\nif (!email || !/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(email)) {\n    showError(\"Enter a valid email.\"); return;\n}\n// reload the page if it has been open long enough for the CSRF token to expire","typeGuard":"// Narrow the server response shape before reading errors:\nfunction hasErrorsArray(json) {\n  return json != null && Array.isArray(json.errors) && json.errors.length > 0;\n}","tryCatchPattern":"try {\n    await sendRequest();\n} catch (e) {\n    // e.message === server's errors[0]\n    showToast(e.message || i18nResources.sendVerificationCodeFailed);\n}","preventionTips":["Refresh long-open forms so the CSRF token does not expire.","Validate the email client-side before sending.","Throttle the send button to avoid rate-limit rejections.","Inspect the response body in DevTools to read the precise errors[0] reason."],"tags":["frontend","javascript","csrf","email-verification","complete-profile"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}