{"record":{"id":"d3d6d6373e1377e8","repo":"withastro/astro","slug":"actionsreturnedinvaliddataerror","errorCode":"ActionsReturnedInvalidDataError","errorMessage":"Action handler returned invalid data. Handlers should return serializable data types like objects, arrays, strings, and numbers. Parse error: ${error}","messagePattern":"Action handler returned invalid data\\. Handlers should return serializable data types like objects, arrays, strings, and numbers\\. Parse error: (.+?)","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/actions/runtime/server.ts","lineNumber":514,"sourceCode":"\t\treturn {\n\t\t\ttype: 'empty',\n\t\t\tstatus: 204,\n\t\t};\n\t}\n\tlet body;\n\ttry {\n\t\tbody = devalueStringify(res.data, {\n\t\t\t// Add support for URL objects\n\t\t\tURL: (value) => value instanceof URL && value.href,\n\t\t});\n\t} catch (e) {\n\t\tlet hint = ActionsReturnedInvalidDataError.hint;\n\t\tif (res.data instanceof Response) {\n\t\t\thint = REDIRECT_STATUS_CODES.includes(res.data.status as any)\n\t\t\t\t? 'If you need to redirect when the action succeeds, trigger a redirect where the action is called. See the Actions guide for server and client redirect examples: https://docs.astro.build/en/guides/actions.'\n\t\t\t\t: 'If you need to return a Response object, try using a server endpoint instead. See https://docs.astro.build/en/guides/endpoints/#server-endpoints-api-routes';\n\t\t}\n\t\tthrow new AstroError({\n\t\t\t...ActionsReturnedInvalidDataError,\n\t\t\tmessage: ActionsReturnedInvalidDataError.message(String(e)),\n\t\t\thint,\n\t\t});\n\t}\n\treturn {\n\t\ttype: 'data',\n\t\tstatus: 200,\n\t\tcontentType: 'application/json+devalue',\n\t\tbody,\n\t};\n}\nfunction toArrayBuffer(buffer: Uint8Array): ArrayBuffer {\n\tconst copy = new Uint8Array(buffer.byteLength);\n\tcopy.set(buffer);\n\treturn copy.buffer;\n}\n","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/actions/runtime/server.ts#L496-L532","documentation":"The action handler's return value is serialized with devalueStringify (devalue) before being sent to the client. If the data is not devalue-serializable (a Response object, a function, an unsupported class instance, Symbols), serialization fails and AstroError ActionsReturnedInvalidDataError is thrown, with an extra hint when a Response was returned.","triggerScenarios":"Handler returns new Response(...) (e.g. trying to redirect), a custom class instance devalue cannot encode, a function, or Symbol-keyed/Symbol-valued structures.","commonSituations":"Trying to redirect by returning a Response; returning a Mongoose document / ORM model instance; returning a function or Class instance.","solutions":["Return plain serializable data: objects, arrays, strings, numbers, booleans, null, Date, URL (supported via the URL plugin), Maps/Sets.","For redirects, trigger the redirect at the call site (client or Astro.callAction) instead of returning a Response.","If you truly need to return a Response, use a server endpoint (API route) rather than an action.","Convert class instances to plain objects before returning."],"exampleFix":"// before\nexport const go = defineAction({ handler: async () => new Response(null, { status: 302, headers: { Location: '/done' } }) });\n// after - return data, redirect at the call site\nexport const go = defineAction({ handler: async () => ({ ok: true }) });\n// caller (client): const { data } = await actions.go(); if (data?.ok) window.location.href = '/done';","handlingStrategy":"try-catch","validationCode":"// Sanity-check the handler's return shape in dev before returning it.\nfunction assertSerializable(value: unknown) {\n  if (value instanceof Response) throw new Error('Actions cannot return a Response; use an endpoint or redirect at the call site.');\n  if (typeof value === 'function') throw new Error('Actions cannot return a function.');\n}\n// inside handler:\nconst result = await doWork(); assertSerializable(result); return result;","typeGuard":"// Reject non-serializable return types up front.\nfunction isSerializableReturn(v: unknown): boolean {\n  if (v instanceof Response) return false;\n  if (typeof v === 'function' || typeof v === 'symbol') return false;\n  return true;\n}","tryCatchPattern":null,"preventionTips":["Return only devalue-supported types (plain objects/arrays/primitives/Date/URL/Map/Set).","Never return a Response from an action; redirect at the call site instead.","Convert ORM/class instances to plain objects before returning.","Keep the devalue support list handy when designing return shapes."],"tags":["actions","serialization","devalue","response"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}