next.js: Build error when slug ends with `.html` for dynamic routes

Bug report

I have an old site which I’m about to migrate to Next.js. I want to generate static pages. I have to support URLs such as: /blog/article-slug.html (this is the canonical URL that users and search engines see). I found two ways to build such URLs but neither of them seem to work properly.

Describe the bug

Option 1

I create a page component such as pages/blog/[slug].html.js and in getStaticPaths I provide the slug without the .html extension.

export const getStaticPaths = async () => {
    return { fallback: false, paths: [{ params: { slug: 'article-slug' } }] };
};

This options does not work at all. I DEV mode I only get a 404 page if I try to access http://localhost:3000/blog/article-slug.html. When running next build I get

Error: getStaticPaths can only be used with dynamic pages, not ‘/articles/[slug].html’. This means that this page is considered to have a static path and not be a dynamic.

Option 2

I create a page component such as pages/blog/[slug].js and in getStaticPaths I provide the slug with the .html extension.

export const getStaticPaths = async () => {
    return { fallback: false, paths: [{ params: { slug: 'article-slug.html' } }] };
};

This option at least works in DEV mode. But when running next build I get the following error:

> Build error occurred
[Error: ENOENT: no such file or directory, rename '/tmp/next/.next/export/blog/article-slug.html.html' -> '/tmp/next/.next/server/static/78zmPfx5_aE06CmpsBKfD/pages/blog/article-slug.html.html'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'rename',
  path: '/tmp/next/.next/export/blog/article-slug.html.html',
  dest: '/tmp/next/.next/server/static/78zmPfx5_aE06CmpsBKfD/pages/blog/article-slug.html.html'
}

To Reproduce

I created a repo to reproduce these errors:
https://github.com/bdadam/next.js-error-when-.html-in-path

Expected behavior

I would expect that next build generates a file such as .next/export/blog/article-slug.html.html.

System information

  • OS: Linux, Ubuntu 19.10
  • Version of Next.js: 9.3.5
  • Version of Node.js: 13.6.0

Other considerations

I can only reproduce this behavior if the slug ends with .html a . itself in the slug does not seem to cause any problems e.g. article....slug.xhtml.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 7
  • Comments: 15 (1 by maintainers)

Commits related to this issue

Most upvoted comments

I think this could be solved by the new “rewrite” function, though you’ll need a new version of Nextjs. Example:

module.exports = {
    async rewrites() {
        return [
            {
                source: "/:slug*.html",  // Old url with .html
                destination: "/:slug*", // Redirect without .html
            },
        ];
    },   
}

I’m waiting for this issue fixed but until that I’m using the rewrite option. next.config.js

module.exports = {
  async rewrites() {
    return [
      {
        source: "/:slug*.html", // Old url with .html
        destination: "/:slug*", // Redirect without .html
      },
    ];
  },
}