withastro/astro · warning

[RSS] Passing a glob result directly has been deprecated. Pl

Error message

[RSS] Passing a glob result directly has been deprecated. Please migrate to the `pagesGlobToRssItems()` helper: https://docs.astro.build/en/recipes/rss/

What it means

@astrojs/rss validates the `items` option with Zod. Passing the raw result of `import.meta.glob()` — an object mapping file paths to lazy loaders — instead of an array is deprecated: the schema detects the glob shape, prints this yellow deprecation warning, and internally converts it via pagesGlobToRssItems. It still functions, but the direct-glob path is scheduled for removal.

Source

Thrown at packages/astro-rss/src/index.ts:76

type ValidatedRSSFeedItem = z.infer<typeof rssSchema>;
type ValidatedRSSOptions = z.infer<typeof rssOptionsValidator>;
type GlobResult = z.infer<typeof globResultValidator>;

const globResultValidator = z.record(
	z.string(),
	z.function({ input: [], output: z.promise(z.any()) }),
);

const rssOptionsValidator = z.object({
	title: z.string(),
	description: z.string(),
	site: z.preprocess((url) => (url instanceof URL ? url.href : url), z.string().url()),
	items: z
		.array(rssSchema)
		.or(globResultValidator)
		.transform((items) => {
			if (!Array.isArray(items)) {
				console.warn(
					colors.yellow(
						'[RSS] Passing a glob result directly has been deprecated. Please migrate to the `pagesGlobToRssItems()` helper: https://docs.astro.build/en/recipes/rss/',
					),
				);
				return pagesGlobToRssItems(items);
			}
			return items;
		}),
	xmlns: z.record(z.string(), z.unknown()).optional(),
	stylesheet: z.union([z.string(), z.boolean()]).optional(),
	customData: z.string().optional(),
	trailingSlash: z.boolean().default(true),
});

export default async function getRssResponse(rssOptions: RSSOptions): Promise<Response> {
	const rssString = await getRssString(rssOptions);
	return new Response(rssString, {
		headers: {

View on GitHub (pinned to 52e6c34790)

Solutions

  1. Wrap the glob: `items: await pagesGlobToRssItems(import.meta.glob('./pages/**/*.md'))`
  2. Or map glob entries yourself to an array of `{ link, title, pubDate }` objects
  3. Ensure items ends up a plain array so the deprecation transform never engages

Example fix

// before (deprecated)
import rss from '@astrojs/rss';
export const GET = ({ site }) => rss({
  title: 'Blog', description: '...', site,
  items: import.meta.glob('./pages/*.md'),
});

// after
import rss from '@astrojs/rss';
import { pagesGlobToRssItems } from '@astrojs/rss';
export const GET = async ({ site }) => rss({
  title: 'Blog', description: '...', site,
  items: await pagesGlobToRssItems(import.meta.glob('./pages/*.md')),
});
Defensive patterns

Strategy: validation

Validate before calling

// Normalize items before passing to rss() so the deprecation never triggers
import { pagesGlobToRssItems } from '@astrojs/rss';
const raw = import.meta.glob('./pages/*.md');
const items = Array.isArray(raw) ? raw : await pagesGlobToRssItems(raw);

Type guard

type GlobResult = Record<string, () => Promise<unknown>>;
const isGlobResult = (v: unknown): v is GlobResult =>
  typeof v === 'object' && v !== null && !Array.isArray(v) && Object.values(v).every((f) => typeof f === 'function');

Prevention

When it happens

Trigger: An RSS endpoint with `items: import.meta.glob('./pages/*.md')` — the glob result object flows into the validator, triggers the warning, and is auto-converted.

Common situations: Older tutorials and pre-helper example code; upgrading @astrojs/rss to versions that introduced `pagesGlobToRssItems()`.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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