diff --git a/.changeset/flat-baboons-nail.md b/.changeset/flat-baboons-nail.md new file mode 100644 index 0000000000..128d4234ba --- /dev/null +++ b/.changeset/flat-baboons-nail.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Prevent frontmatter errors from crashing the dev server diff --git a/packages/astro/src/content/types-generator.ts b/packages/astro/src/content/types-generator.ts index e695f9e602..ab0e254add 100644 --- a/packages/astro/src/content/types-generator.ts +++ b/packages/astro/src/content/types-generator.ts @@ -226,8 +226,17 @@ export async function createContentTypesGenerator({ events.push(event); debounceTimeout && clearTimeout(debounceTimeout); + const runEventsSafe = async () => { + try { + await runEvents(opts); + } catch { + // Prevent frontmatter errors from crashing the server. The errors + // are still reported on page reflects as desired. + // Errors still crash dev from *starting*. + } + }; debounceTimeout = setTimeout( - async () => runEvents(opts), + runEventsSafe, 50 /* debounce to batch chokidar events */ ); } diff --git a/packages/astro/test/units/content-collections/frontmatter.test.js b/packages/astro/test/units/content-collections/frontmatter.test.js new file mode 100644 index 0000000000..d4a9f1ecee --- /dev/null +++ b/packages/astro/test/units/content-collections/frontmatter.test.js @@ -0,0 +1,72 @@ +import { fileURLToPath } from 'node:url'; +import nodeFS from 'node:fs'; +import path from 'node:path'; +import slash from 'slash'; + +import { runInContainer } from '../../../dist/core/dev/index.js'; +import { attachContentServerListeners } from '../../../dist/content/index.js'; +import { createFs, triggerFSEvent } from '../test-utils.js'; + +const root = new URL('../../fixtures/alias/', import.meta.url); + +function getTypesDts() { + const typesdtsURL = new URL('../../../src/content/template/types.d.ts', import.meta.url); + const relpath = slash(path.relative(fileURLToPath(root), fileURLToPath(typesdtsURL))); + return { + [relpath]: nodeFS.readFileSync(typesdtsURL, 'utf-8') + }; +} + +describe('frontmatter', () => { + it('errors in content/ does not crash server', async () => { + const fs = createFs( + { + ...getTypesDts(), + '/src/content/posts/blog.md': ` + --- + title: One + --- + `, + '/src/content/config.ts': ` + import { defineCollection, z } from 'astro:content'; + + const posts = defineCollection({ + schema: z.string() + }); + + export const collections = { + posts + }; + `, + '/src/pages/index.astro': ` + --- + --- + +