{"record":{"id":"1eec47016b735560","repo":"withastro/astro","slug":"unsupported-media-type","errorCode":"UNSUPPORTED_MEDIA_TYPE","errorMessage":"This action only accepts FormData.","messagePattern":"This action only accepts FormData\\.","errorType":"exception","errorClass":"ActionError","httpStatus":415,"severity":"error","filePath":"packages/astro/src/actions/runtime/server.ts","lineNumber":81,"sourceCode":"\tObject.assign(safeServerHandler, {\n\t\torThrow(this: ActionAPIContext, unparsedInput: unknown) {\n\t\t\tif (typeof this === 'function') {\n\t\t\t\tthrow new AstroError(ActionCalledFromServerError);\n\t\t\t}\n\t\t\treturn serverHandler(unparsedInput, this);\n\t\t},\n\t});\n\n\treturn safeServerHandler as ActionClient<TOutput, TAccept, TInputSchema> & string;\n}\n\nfunction getFormServerHandler<TOutput, TInputSchema extends z.$ZodType>(\n\thandler: ActionHandler<TInputSchema, TOutput>,\n\tinputSchema?: TInputSchema,\n) {\n\treturn async (unparsedInput: unknown, context: ActionAPIContext): Promise<Awaited<TOutput>> => {\n\t\tif (!(unparsedInput instanceof FormData)) {\n\t\t\tthrow new ActionError({\n\t\t\t\tcode: 'UNSUPPORTED_MEDIA_TYPE',\n\t\t\t\tmessage: 'This action only accepts FormData.',\n\t\t\t});\n\t\t}\n\n\t\tif (!inputSchema) return await handler(unparsedInput, context);\n\n\t\tconst parsed = await parseFormInput(inputSchema, unparsedInput);\n\n\t\tif (!parsed.success) {\n\t\t\tthrow new ActionInputError(parsed.error.issues);\n\t\t}\n\t\treturn await handler(parsed.data, context);\n\t};\n}\n\nasync function parseFormInput(inputSchema: z.$ZodType, unparsedInput: FormData) {\n\tconst baseSchema = unwrapBaseZ4ObjectSchema(inputSchema, unparsedInput);","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/actions/runtime/server.ts#L63-L99","documentation":"An action defined with accept: 'form' is wired to a form-specific server handler that requires its input to be a FormData instance (so it can run form parsing and the zod form path). If such an action receives any other value — a plain object, string, or URLSearchParams — the handler rejects it with ActionError code UNSUPPORTED_MEDIA_TYPE.","triggerScenarios":"Calling an accept:'form' action from client code with a plain object: actions.subscribe({ email }) instead of FormData. Calling it from server code with a parsed object. Submitting programmatically built data without wrapping it in new FormData().","commonSituations":"Switching an action to accept:'form' for progressive enhancement but leaving JSON-style call sites; testing actions with object literals; reusing one call path for both json and form actions.","solutions":["Build and pass FormData: const fd = new FormData(); fd.set('email', email); await actions.subscribe(fd)","If calling from a real HTML form, pass the form element or its FormData (new FormData(formEl))","If you actually want JSON input on this action, remove accept: 'form' from defineAction"],"exampleFix":"// before\nawait actions.subscribe({ email: 'a@b.c' }); // accept:'form' action\n\n// after\nconst fd = new FormData();\nfd.set('email', 'a@b.c');\nawait actions.subscribe(fd);","handlingStrategy":"type-guard","validationCode":"// verify you are sending what an accept:'form' action expects\nif (!(payload instanceof FormData)) {\n  const fd = new FormData();\n  for (const [k, v] of Object.entries(payload)) fd.set(k, String(v));\n  payload = fd;\n}\nawait actions.subscribe(payload);","typeGuard":"function isFormData(v: unknown): v is FormData {\n  return typeof FormData !== 'undefined' && v instanceof FormData;\n}","tryCatchPattern":"try {\n  await actions.subscribe(fd);\n} catch (e) {\n  if (e instanceof ActionError && e.code === 'UNSUPPORTED_MEDIA_TYPE') {\n    // convert input to FormData (or switch the action to JSON) and retry\n  } else throw e;\n}","preventionTips":["Match call-site input type to the action's accept option: form -> FormData, default -> plain object","Build FormData with new FormData(formElement) from real forms to keep types aligned","Document the accept mode in the action name or JSDoc when a project mixes both styles"],"tags":["astro-actions","form-data","unsupported-media-type","input-type"],"backgroundTag":"content-type-mismatch","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}