withastro/astro · error · AstroError

UnsupportedConfigTransformError

UnsupportedConfigTransformError

Error message

`transform()` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).
Full error: ${parseError}

What it means

Thrown when a `transform()` function in a content collection schema returns a value that cannot be serialized by the devalue library. After the transform runs, the plugin attempts to serialize the result for the virtual module; if devalue encounters an unsupported type (e.g. a class instance, a function, a Symbol, a circular reference), it throws, and the error is wrapped as `UnsupportedConfigTransformError`.

Source

Thrown at packages/astro/src/content/vite-plugin-content-imports.ts:434

/** Stringify entry `data` at build time to be used as a Vite module */
function stringifyEntryData(data: Record<string, any>, isSSR: boolean): string {
	try {
		return devalue.uneval(data, (value) => {
			// Add support for URL objects
			if (value instanceof URL) {
				return `new URL(${JSON.stringify(value.href)})`;
			}

			// For Astro assets, add a proxy to track references
			if (typeof value === 'object' && 'ASTRO_ASSET' in value) {
				const { ASTRO_ASSET, ...asset } = value;
				asset.fsPath = ASTRO_ASSET;
				return getProxyCode(asset, isSSR);
			}
		});
	} catch (e) {
		if (e instanceof Error) {
			throw new AstroError({
				...AstroErrorData.UnsupportedConfigTransformError,
				message: AstroErrorData.UnsupportedConfigTransformError.message(e.message),
				stack: e.stack,
			});
		} else {
			throw new AstroError({
				name: 'PluginContentImportsError',
				message: 'Unexpected error processing content collection data.',
			});
		}
	}
}

View on GitHub (pinned to d081033d5f)

Solutions

  1. Return only JSON-compatible types or devalue-supported types (Date, Map, Set, URL, RegExp, BigInt, TypedArray).
  2. Convert class instances to plain objects before returning from transform.
  3. Break circular references or use a structure that avoids them.
  4. Read the devalue parse error in the message — it names the unsupported type.

Example fix

// before
schema: z.object({
  date: z.string().transform((s) => {
    const d = new MyCustomDate(s); // class instance — not serializable
    return d;
  }),
}),

// after
schema: z.object({
  date: z.coerce.date(), // native Date — devalue supports it
}),
Defensive patterns

Strategy: validation

Validate before calling

import { stringify } from 'devalue';
function isSerializable(value: unknown): boolean {
  try { stringify(value); return true; } catch { return false; }
}

Try / catch

try {
  const result = await getCollection('blog');
} catch (e) {
  if (e instanceof Error && /UnsupportedConfigTransformError/.test(e.name)) {
    console.error('Transform returned non-serializable data:', e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: A collection schema uses `.transform()` (or Zod's `.transform()`) and the transform returns a non-serializable value. The `stringify`/devalue serialization step in the content imports plugin throws, the catch block wraps it with the full devalue parse error message.

Common situations: A transform returns a class instance (e.g. `new Date()` is fine, but `new MyClass()` is not). A transform returns a function or callback. A circular object reference in transformed data. Returning a Map with non-serializable keys or a Symbol-keyed object.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/35d38ff99b58edf0. Report an issue: GitHub.