Skip to content

fix: handle missing videos directory in getVideoSlugs (auto)#18015

Draft
pettinarip wants to merge 1 commit intodevfrom
recovery/fix/grafana-fn-error-enoent-sitemap-videos-scandir
Draft

fix: handle missing videos directory in getVideoSlugs (auto)#18015
pettinarip wants to merge 1 commit intodevfrom
recovery/fix/grafana-fn-error-enoent-sitemap-videos-scandir

Conversation

@pettinarip
Copy link
Copy Markdown
Member

Summary

  • app/sitemap.ts throws ENOENT at runtime on Netlify because getVideoSlugs() does a raw readdir on public/content/videos, and that directory isn't bundled into serverless functions.
  • getPostSlugs already guards the same failure mode in src/lib/utils/md.ts; this PR applies the same ENOENT handling to getVideoSlugs so the sitemap degrades gracefully instead of 500ing.
  • Build-time behaviour is unchanged: when the directory exists (as it does during pnpm build), all video slugs are still returned.

Error Context

  • Source: grafana-logs
  • Item ID: grafana-fn-error-enoent-no-such-file-or-directory-scandir-x-at-async-o-next-se
  • Path/URL: /sitemap.xml (Netlify Function .next/server/app/sitemap.xml/route.js)
  • Status: 500 (ENOENT thrown from route handler)
  • Hit count: 100
  • Request ID (sample): 01KPTG6Z7AXST53NM89RZFZAYE
  • First seen: 2026-04-22 (recently; introduced by videos-refactor re-merge on 2026-04-13)

Changes

  • src/lib/utils/videos.ts: wrap the readdir(videosDir, ...) call in getVideoSlugs() with a try/catch that maps ENOENT to an empty slug list (with a console.warn), mirroring the graceful fallback already implemented in getPostSlugs (src/lib/utils/md.ts:64-74).

Analysis

Stack trace points at /var/task/.next/server/app/sitemap.xml/route.js and a scandir on /var/task/public/content/videos. That's the Netlify Functions sandbox path — public/content/* is only bundled into functions when explicitly listed in netlify.toml's included_files, which today lists i18n.config.json, src/intl/**/*, and src/data-layer/mocks/**/*, but not public/content/videos.

app/sitemap.ts was updated on 2026-04-13 (videos-refactor PR #17870 reapply) to call getVideoSlugs() so the sitemap picks up /videos/<slug>/ URLs. The individual video pages are statically generated at build time (app/[locale]/videos/[slug]/page.tsx uses generateStaticParams), so they don't hit this path — but app/sitemap.ts does.

getPostSlugs in src/lib/utils/md.ts handles this same environmental mismatch by catching ENOENT and returning [] with a warning. getVideoSlugs didn't — so any time Netlify invokes the sitemap route at runtime (regardless of why), we throw. 100 hits in the Grafana logs confirms it's firing consistently.

Matching the existing pattern keeps the fix small and consistent with the codebase's accepted trade-off: at build time we emit a complete sitemap with video URLs; if the sitemap route is re-executed at runtime without the content bundle, we still return a valid (video-less) sitemap instead of 500ing.

Related issue: #18014 tracks the broader WARN-level variant of this same root cause from getPostSlugs.

Test Plan

  • Verify the draft PR triggers a clean Netlify deploy preview.
  • Load /sitemap.xml on the preview — expect 200, with /videos/<slug>/ entries present (built once at build time).
  • Confirm Grafana error rate for this signature drops to zero after the PR lands on dev.
  • Optionally consider forcing the sitemap to export const dynamic = 'force-static' in a follow-up so runtime re-invocation never drops video URLs; out of scope here.

Opened automatically by the Recovery Agent.

Resolves grafana-logs item grafana-fn-error-enoent-no-such-file-or-directory-scandir-x-at-async-o-next-se.

The sitemap.xml route calls getVideoSlugs(), which does a readdir on
public/content/videos. Netlify Functions don't bundle public/ content,
so the call throws ENOENT at runtime (100 hits in Grafana logs).
getPostSlugs already mirrors this degradation pattern for the same
root cause; getVideoSlugs now matches by catching ENOENT and returning
an empty slug list.
@pettinarip pettinarip added the recovery-agent Created by the Recovery Agent label Apr 22, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

Deploy Preview for ethereumorg ready!

Name Link
🔨 Latest commit 2621401
🔍 Latest deploy log https://app.netlify.com/projects/ethereumorg/deploys/69e8b9e2262bf80008352e27
😎 Deploy Preview https://deploy-preview-18015.ethereum.it
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
7 paths audited
Performance: 58 (no change from production)
Accessibility: 93 (no change from production)
Best Practices: 100 (no change from production)
SEO: 98 (🔴 down 1 from production)
PWA: 59 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added the tooling 🔧 Changes related to tooling of the project label Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

recovery-agent Created by the Recovery Agent tooling 🔧 Changes related to tooling of the project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants