withastro/astro · error · AstroError

InvalidContentEntrySlugError

InvalidContentEntrySlugError

Error message

${String(collection)} → ${String(entryId)} has an invalid slug. `slug` must be a string.

What it means

While syncing markdown/MDX entries, Astro validates the optional frontmatter slug with z.string(), falling back to the filename-generated slug when absent. If a slug field is present but not a string — a number, boolean, list, or unquoted YAML date — parsing fails and the error names the offending collection and entry id.

Solutions

  1. Open the named entry and make the slug a quoted string: slug: "123".
  2. Remove the slug field entirely to fall back to the generated filename slug.
  3. If a script or CMS writes the frontmatter, stringify the slug value before writing.

Example fix

# before
---
slug: 2024-05-01
title: My post
---

# after
---
slug: "2024-05-01"
title: My post
---
Defensive patterns

Strategy: validation

Validate before calling

// Pre-build check: frontmatter slug must be a quoted string when present
import { readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';
for (const file of await readdir('src/content', { recursive: true })) {
  if (!String(file).endsWith('.md')) continue;
  const lines = (await readFile(join('src/content', file), 'utf8')).split('\n');
  const slugLine = lines.find((l) => l.startsWith('slug:'));
  if (!slugLine) continue;
  const value = slugLine.slice(5).trim();
  const quoted = value.startsWith('"') || value.startsWith("'");
  if (!quoted) console.error(`slug needs quotes in ${file}: ${value}`);
}

Prevention

When it happens

Trigger: Frontmatter such as slug: 123 (number), slug: [a, b] (list), slug: true, or slug: 2024-05-01 which YAML parses as a date; any non-string value the CMS or a script writes into the slug field.

Common situations: Numeric or date-like slugs left unquoted in YAML; CMS exports that emit typed values; frontmatter templates that default slug to null.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18). Data as JSON: /api/errors/0097d5e8655cd6b5. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/content/utils.ts:149

export type CollectionConfig = ContentConfig['collections'][string];

type EntryInternal = { rawData: string | undefined; filePath: string };

export function parseEntrySlug({
	id,
	collection,
	generatedSlug,
	frontmatterSlug,
}: {
	id: string;
	collection: string;
	generatedSlug: string;
	frontmatterSlug?: unknown;
}) {
	try {
		return z.string().default(generatedSlug).parse(frontmatterSlug);
	} catch {
		throw new AstroError({
			...AstroErrorData.InvalidContentEntrySlugError,
			message: AstroErrorData.InvalidContentEntrySlugError.message(collection, id),
		});
	}
}

export async function getEntryData<
	TInputData extends Record<string, unknown> = Record<string, unknown>,
	TOutputData extends TInputData = TInputData,
>(
	entry: {
		id: string;
		collection: string;
		unvalidatedData: TInputData;
		_internal: EntryInternal;
	},
	collectionConfig: CollectionConfig,
	shouldEmitFile: boolean,

View on GitHub (pinned to e294953aa8)