#Netlify Form handling

14 messages · Page 1 of 1 (latest)

indigo pivot
#

I'm using astro actions to handle my form submission but its not working for some reason?

    <form class="form" method="post" action={actions.form} novalidate>

On my dev server the email is being sent, but on my deploy branch (preview branch on netlify) - I keep getting a 500 error. The netlify logs arent telling me anything

heavy larkBOT
#

Hi @indigo pivot. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Astro’s docs don’t describe your exact 500 error scenario, so some of this will be necessarily high‑level. But there are a few deployment‑specific requirements and tools you can check.

  1. Confirm the page is on-demand rendered (not prerendered)
    Actions only work with server output. If the page containing your form is prerendered, calling an action will fail at runtime. Ensure prerendering is disabled on that page (or globally use a server adapter like @astrojs/netlify and mark the page for on‑demand rendering). [Actions error list; Actions must use server output]

  2. Use the HTML form → action pattern exactly as documented
    The pattern you’re using matches the docs: a <form method="POST" action={actions.someAction}> that posts directly to the action. [Call actions from form]
    Example from the docs:

    --- 
    import { actions } from 'astro:actions';
    ---
    <form method="POST" action={actions.newsletter}>
      <label>
        E-mail
        <input required type="email" name="email" />
      </label>
      <button>Sign up</button>
    </form>
    

    Double‑check that:

    • The action is exported correctly from src/actions/index.ts (e.g. export const server = { form: defineAction({ … }) }).
    • The name you use in actions.form matches the key in server.
#
  1. Check for action‑specific runtime errors
    Actions can fail due to validation or handler errors, which will surface as 500s. The docs recommend always checking error vs data when you read the result with Astro.getActionResult(). [Handling returned data]
    If you’re using accept: 'form', make sure your Zod schema matches the actual form fields and types. [Accepting form data; Validating form data]

  2. Netlify‑specific behavior (skew protection & sessions)

    • The Netlify adapter automatically injects a deploy ID header into internal requests for actions, which prevents version skew during deploys. [Netlify skew protection]
    • If you’re using the advanced POST/Redirect/GET pattern with middleware and Netlify Blob (for persisting action results), ensure that middleware is deployed and that Blob access is configured correctly; otherwise, the middleware path can throw 500s. [Persist action results with session]
#
  1. How to debug further (within Astro’s patterns)
    The docs don’t give a direct recipe for Netlify 500 debugging, but you can:
    • Temporarily simplify your action handler to a trivial success (e.g. return a static object) to see if the 500 is caused by your email‑sending code vs. the action wiring itself.
    • Use Astro.getActionResult(actions.form) on the page to render any error message to the UI, which can help distinguish validation vs. internal errors. [Handle form action errors]

Because the knowledge sources don’t include Netlify‑specific 500 troubleshooting steps or logs, I can’t say exactly why your preview deploy fails while dev works. But based on the docs, the first things to verify are:

  • The page is not prerendered and is using a server adapter.
  • The action is defined and exported correctly and uses accept: 'form' if you’re posting form data.
  • Any advanced middleware/session logic (if you’re using it) is correctly configured on Netlify.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@indigo pivot Kapa.ai is still learning and improving, please let me know how I did by reacting below.

indigo pivot
#

my contact.astro page has export const prerender = false; declared.
I have adapter: netlify() setup in my astro.config.mjs as well.

Give me the code to render any error messages on the UI please @heavy lark

heavy larkBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Here’s a minimal pattern using Astro.getActionResult() to show any errors from your form action on the contact page UI.

Assuming you have an action named form in src/actions/index.ts, your src/pages/contact.astro can look like this:

---
import { actions, isInputError } from 'astro:actions';

export const prerender = false;

const result = Astro.getActionResult(actions.form);
const inputErrors = isInputError(result?.error) ? result.error.fields : {};
---

{result?.error && !isInputError(result.error) && (
  <p class="error">Something went wrong. Please try again later.</p>
)}

<form class="form" method="POST" action={actions.form} novalidate>
  <label>
    Email
    <input
      type="email"
      name="email"
      aria-describedby="email-error"
      required
    />
  </label>
  {inputErrors.email && (
    <p id="email-error" class="error">
      {inputErrors.email.join(', ')}
    </p>
  )}

  <!-- add your other fields here, using inputErrors.fieldName similarly -->

  <button type="submit">Send</button>
</form>

This does two things:

  1. Shows a general error message when the action fails for any non‑validation reason. [Handle form errors]
  2. Uses isInputError() to render field‑specific validation messages (example shown for email). [Displaying input errors]

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@indigo pivot Kapa.ai is still learning and improving, please let me know how I did by reacting below.

indigo pivot
#

This just gives me a general error message though. I wont be able to do anything with that information @heavy lark

heavy larkBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You can surface the actual ActionError details (code/message) and, for validation errors, the per‑field messages. Astro exposes all of this on the action result; you just need to render it.

1. Show full ActionError details

---
import { actions, isInputError } from 'astro:actions';

export const prerender = false;

const result = Astro.getActionResult(actions.form);
const inputErrors = isInputError(result?.error) ? result.error.fields : {};
---

{result?.error && (
  <div class="error-block">
    <p><strong>Action failed</strong></p>
    <p><code>code:</code> {result.error.code}</p>
    {result.error.message && (
      <p><code>message:</code> {result.error.message}</p>
    )}
  </div>
)}

<form class="form" method="POST" action={actions.form} novalidate>
  <!-- example field -->
  <label>
    Email
    <input
      type="email"
      name="email"
      aria-describedby="email-error"
      required
    />
  </label>
  {inputErrors.email && (
    <p id="email-error" class="error">
      {inputErrors.email.join(', ')}
    </p>
  )}

  <button type="submit">Send</button>
</form>
  • Astro.getActionResult(actions.form) gives you the error object from the action. [Handle form action errors]
  • That error is an ActionError with .code and optional .message, which you can render directly. [ActionError]

2. See all validation errors

If your action uses input: z.object({ ... }), isInputError() lets you inspect all field errors:

---
import { actions, isInputError } from 'astro:actions';

export const prerender = false;

const result = Astro.getActionResult(actions.form);
const inputErrors = isInputError(result?.error) ? result.error.fields : {};
---
#

{isInputError(result?.error) && (
<pre class="debug">
{JSON.stringify(result.error.fields, null, 2)}
</pre>
)}

<form method="POST" action={actions.form} novalidate>
<!-- repeat this pattern for each field -->
<label>
Name
<input name="name" aria-describedby="name-error" />
</label>
{inputErrors.name && (
<p id="name-error" class="error">
{inputErrors.name.join(', ')}
</p>
)}

<button>Send</button>
</form>


`result.error.fields` contains an array of messages per field name, which you can both debug with `<pre>` and wire into your UI. [[Displaying form input errors](<https://docs.astro.build/en/guides/actions/#displaying-form-input-errors>); [isInputError](<https://docs.astro.build/en/reference/modules/astro-actions/#isinputerror>)]
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------