{"record":{"id":"35d38ff99b58edf0","repo":"withastro/astro","slug":"unsupportedconfigtransformerror","errorCode":"UnsupportedConfigTransformError","errorMessage":"`transform()` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).\nFull error: ${parseError}","messagePattern":"`transform\\(\\)` functions in your content config must return valid JSON, or data types compatible with the devalue library \\(including Dates, Maps, and Sets\\)\\.\nFull error: (.+?)","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/content/vite-plugin-content-imports.ts","lineNumber":435,"sourceCode":"/** Stringify entry `data` at build time to be used as a Vite module */\nfunction stringifyEntryData(data: Record<string, any>, isSSR: boolean): string {\n\ttry {\n\t\treturn devalue.uneval(data, (value) => {\n\t\t\t// Add support for URL objects\n\t\t\tif (value instanceof URL) {\n\t\t\t\treturn `new URL(${JSON.stringify(value.href)})`;\n\t\t\t}\n\n\t\t\t// For Astro assets, add a proxy to track references\n\t\t\tif (typeof value === 'object' && 'ASTRO_ASSET' in value) {\n\t\t\t\tconst { ASTRO_ASSET, ...asset } = value;\n\t\t\t\tasset.fsPath = ASTRO_ASSET;\n\t\t\t\treturn getProxyCode(asset, isSSR);\n\t\t\t}\n\t\t});\n\t} catch (e) {\n\t\tif (e instanceof Error) {\n\t\t\tthrow new AstroError({\n\t\t\t\t...AstroErrorData.UnsupportedConfigTransformError,\n\t\t\t\tmessage: AstroErrorData.UnsupportedConfigTransformError.message(e.message),\n\t\t\t\tstack: e.stack,\n\t\t\t});\n\t\t} else {\n\t\t\tthrow new AstroError({\n\t\t\t\tname: 'PluginContentImportsError',\n\t\t\t\tmessage: 'Unexpected error processing content collection data.',\n\t\t\t});\n\t\t}\n\t}\n}\n","sourceCodeStart":417,"sourceCodeEnd":448,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/content/vite-plugin-content-imports.ts#L417-L448","documentation":"Collection entries are serialized with devalue so they can be stored in the data store and re-hydrated inside generated modules. A transform() function in your loader config must return JSON-compatible values (plus devalue-supported types like Date, Map, Set). When devalue's stringify encounters something it cannot handle — a function, symbol, class instance, or undefined inside an array — the error is wrapped as UnsupportedConfigTransformError with the parse error attached.","triggerScenarios":"A transform() returning functions (href: (slug) => ...), symbols, class or model instances, Moment/Luxon wrappers, or undefined stored in arrays; cyclic structures.","commonSituations":"Returning ORM entities or rich objects from a loader transform; leaving helper functions attached to data; porting code that relied on structuredClone or JSON.stringify semantics that silently dropped functions.","solutions":["Map class instances to plain objects and strip functions before returning from transform().","Convert wrapped types to primitives or built-ins: Moment to Date, Decimal to string, URL is supported natively.","Add a unit test that runs devalue.stringify() over your transform output (see validation below)."],"exampleFix":"// before\nloader: {\n  async load() {},\n  transform(entry) {\n    return { ...entry, published: new Moment(entry.date), href: (slug) => `/posts/${slug}` };\n  },\n}\n\n// after\nloader: {\n  async load() {},\n  transform(entry) {\n    return { ...entry, published: new Date(entry.date) };\n  },\n}","handlingStrategy":"validation","validationCode":"// Unit-test transform output with the same serializer Astro uses\nimport { stringify } from 'devalue';\n\ntest('loader transform output is serializable', () => {\n  for (const entry of sampleEntries) {\n    expect(() => stringify(myTransform(entry))).not.toThrow();\n  }\n});","typeGuard":"const isPlainSerializable = (v: unknown): boolean =>\n  v === null ||\n  ['string', 'number', 'boolean'].includes(typeof v) ||\n  v instanceof Date ||\n  v instanceof Map ||\n  v instanceof Set ||\n  (Array.isArray(v) && v.every(isPlainSerializable)) ||\n  (typeof v === 'object' && Object.values(v).every(isPlainSerializable));","tryCatchPattern":null,"preventionTips":["Return plain objects from transform(); convert class instances and wrapper types explicitly.","Never attach functions to transformed data.","Cover transforms with the devalue stringify test shown above in CI."],"tags":["content-collections","loaders","transform","serialization","devalue"],"backgroundTag":"serialization-failed","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}