Skip to content

[recovery] Return 404 for non-existent story slugs#18783

Draft
pettinarip wants to merge 1 commit into
devfrom
recovery/fix/stories-slug-404
Draft

[recovery] Return 404 for non-existent story slugs#18783
pettinarip wants to merge 1 commit into
devfrom
recovery/fix/stories-slug-404

Conversation

@pettinarip

Copy link
Copy Markdown
Member

Error context

Production error captured from Netlify logs (Grafana → Keep):

[ERROR] Error: ENOENT: no such file or directory, open '/var/task/public/content/stories/-6/index.md'
    at async Object.readFileFallbackBlobStore [as readFile] (.netlify/dist/run/next.cjs:554:16)
    ...
    at async Module.t [as generateMetadata] (...)
  • Path: /var/task/public/content/stories/-6/index.md (request to /stories/-6/)
  • Hit count: 2 (first seen 2026-06-10)

Root cause

The stories [slug] route (app/[locale]/stories/[slug]/page.tsx) reads the markdown file directly — in both the page body (getPageData) and generateMetadata (getMdMetadataimportMdfs.readFile) — without guarding against non-existent slugs. /stories/ has generateStaticParams, but with default dynamicParams, unknown slugs like -6 (a crawler/bot probe) are rendered on demand. generateMetadata then throws an unhandled ENOENT, surfacing as a 500 in the Netlify server handler instead of a 404.

The shared catch-all [...slug] route already handles this exact case: it validates the path and calls notFound(), and wraps getMdMetadata in a try/catch returning basic not-found metadata. The stories route was written without that guard.

Fix

Mirror the catch-all route's handling:

  • Page body: validate slug against getStorySlugs() and call notFound() for unknown slugs.
  • generateMetadata: wrap getMdMetadata in a try/catch that returns basic not-found metadata.

Single-file change. pnpm type-check passes and ESLint is clean.

Affected files

  • app/[locale]/stories/[slug]/page.tsx

🤖 Generated with Claude Code

The stories [slug] route read the markdown file directly in both the page
body and generateMetadata without guarding against missing slugs. A crawler
probe to /stories/-6/ threw an unhandled ENOENT during generateMetadata,
surfacing as a 500 in the Netlify server handler.

Mirror the shared [...slug] route: validate the slug against getStorySlugs()
and call notFound() in the page, and wrap getMdMetadata in a try/catch that
returns basic not-found metadata.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pettinarip pettinarip added the recovery-agent Created by the Recovery Agent label Jul 13, 2026
@netlify

netlify Bot commented Jul 13, 2026

Copy link
Copy Markdown

Deploy Preview for ethereumorg ready!

Name Link
🔨 Latest commit 985f393
🔍 Latest deploy log https://app.netlify.com/projects/ethereumorg/deploys/6a55527a948fb00008342a52
😎 Deploy Preview https://deploy-preview-18783.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: 59 (🟢 up 3 from production)
Accessibility: 95 (no change from production)
Best Practices: 100 (no change from production)
SEO: 98 (no change from production)
PWA: 59 (🔴 down 1 from production)
View the detailed breakdown and full score reports

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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant