withastro/astro · warning

No pages found!

Error message

No pages found!

What it means

When the Sitemap integration's serialize option is provided, it maps every generated SitemapItem through the user's serialize() callback and collects truthy return values. If the callback returns falsy for every item (or returns nothing), serializedUrls ends up empty, this 'No pages found!' warning prints, and the sitemap write is skipped entirely.

Source

Thrown at packages/integrations/sitemap/src/index.ts:193

					if (pageUrls.length === 0) {
						logger.warn(`No pages found!\n\`${outFile}\` not created.`);
						return;
					}

					let urlData = generateSitemap(pageUrls, finalSiteUrl.href, opts);

					if (serialize) {
						try {
							const serializedUrls: SitemapItem[] = [];
							for (const item of urlData) {
								const serialized = await Promise.resolve(serialize(item));
								if (serialized) {
									serializedUrls.push(serialized);
								}
							}
							if (serializedUrls.length === 0) {
								logger.warn('No pages found!');
								return;
							}
							urlData = serializedUrls;
						} catch (err) {
							logger.error(`Error serializing pages\n${(err as any).toString()}`);
							return;
						}
					}

					const destDir = fileURLToPath(dir);
					const lastmod = opts.lastmod?.toISOString();
					const xslURL = opts.xslURL ? new URL(opts.xslURL, finalSiteUrl).href : undefined;

					if (chunks) {
						try {
							let groupedUrlCollection: SitemapItem['url'][] = [];
							const chunksItem: Record<string, SitemapItem[]> = {};
							for (const [key, cb] of Object.entries(chunks)) {

View on GitHub (pinned to 157c500c38)

Solutions

  1. Make serialize return the (possibly modified) item for pages you want kept: serialize: (item) => ({ ...item, changefreq: 'daily' }).
  2. Return undefined only for items you intentionally want dropped, and verify at least one path returns an object.
  3. Log item.url inside serialize once to confirm the callback runs and reaches a return statement.
  4. Remove the serialize option temporarily to verify the sitemap generates, then re-add it incrementally.

Example fix

// before
sitemap({
  serialize: (item) => {
    if (item.url.includes('/docs')) { // condition matches nothing on this site
      return { ...item, changefreq: 'weekly' };
    }
  },
}),

// after
sitemap({
  serialize: (item) => ({
    ...item,
    changefreq: item.url.includes('/docs') ? 'weekly' : 'monthly',
  }),
}),
Defensive patterns

Strategy: validation

Validate before calling

const probe = { url: 'https://www.example.com/', lastmod: new Date() };
const result = serialize(probe);
if (!result) {
  throw new Error('serialize() must return an item for at least some inputs; sitemap would be empty');
}

Prevention

When it happens

Trigger: Passing serialize: (item) => { ... } whose logic returns undefined for all items — e.g. a conditional that never matches, a mapping that builds an object but forgets to return it, or returning null to 'skip' every page. The serializedUrls.length === 0 branch fires.

Common situations: A serialize callback copied from docs where the return statement was trimmed; logic intended to exclude only some pages accidentally excluding all; early returns based on changefreq/priority fields that are missing on every item.

Related errors


AI-assisted analysis of withastro/astro@157c500c38 (2026-08-18). Data as JSON: /api/errors/21d89f97b9b06b05. Report an issue: GitHub.