Skip to content

docusaurus serve: static assets 404 when baseUrl is not "/" and trailingSlash is true #12476

Description

@Shashank01729

Have you read the Contributing Guidelines on issues?

Prerequisites

  • I'm using the latest version of Docusaurus.
  • I have tried the npm run clear or yarn clear command.
  • I have tried rm -rf node_modules yarn.lock package-lock.json and re-installing packages.
  • I have tried creating a repro with https://new.docusaurus.io.
  • I have read the console error message carefully (if applicable).

Description

With a non-root baseUrl and trailingSlash: true, docusaurus serve returns 404 for two kinds of static assets:

  • extensions longer than 4 characters — .woff2, .webmanifest, .geojson
  • any asset requested with a query string — /img/logo.png?v=1

Both get a 302 to a trailing-slash URL and end up on the 404 page. Web fonts are the most visible casualty, since .woff2 is the standard format.

It comes from the asset check in packages/docusaurus/src/commands/serve.ts:

const looksLikeAsset = !!req.url.match(/\.[a-zA-Z\d]{1,4}$/);

{1,4} is too short for .woff2, and the $ is matched against the raw req.url, so a ?query also prevents the match. applyTrailingSlash(), called right after it, does split the query off first:

// The trailing slash should be handled before the ?search#hash !
const [pathname] = path.split(/[#?]/) as [string, ...string[]];

The asset check just misses that step.

Reproducible demo

No repo needed — the steps below start from a fresh create-docusaurus install and reproduce it in about a minute.

Steps to reproduce

  1. npx create-docusaurus@latest repro-serve classic --javascript && cd repro-serve && npm install
  2. In docusaurus.config.js, set baseUrl: '/mysite/' and trailingSlash: true
  3. Add three static files:
    printf 'FAKEWOFF2'    > static/custom-font.woff2
    printf '{"name":"x"}' > static/site.webmanifest
    printf 'FAKEPNG'      > static/logo-test.png
  4. npm run build && npm run serve -- --port 3030
  5. Request them:
    curl -sI "http://localhost:3030/mysite/logo-test.png"
    curl -sI "http://localhost:3030/mysite/logo-test.png?v=1"
    curl -sI "http://localhost:3030/mysite/custom-font.woff2"
    curl -sI "http://localhost:3030/mysite/site.webmanifest"

Expected behavior

All four serve the file with status 200 and the correct content type. The trailing slash should only be applied to page URLs, whatever the extension length is and whether or not there is a query string.

Actual behavior

Only the plain .png is served:

/mysite/logo-test.png      -> 200 image/png
/mysite/logo-test.png?v=1  -> 302 .../logo-test.png/?v=1 -> 404 text/html
/mysite/custom-font.woff2  -> 302 .../custom-font.woff2/ -> 404 text/html
/mysite/site.webmanifest   -> 302 .../site.webmanifest/  -> 404 text/html

Following the redirect returns the HTML 404 page instead of the file:

$ curl -sIL "http://localhost:3030/mysite/custom-font.woff2" | grep -E "^HTTP|^Content-Type"
HTTP/1.1 302 Found
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8

Same behavior on main (4.0.0), where the regex is /\.[a-z\d]{1,4}$/i.

Splitting off the query/hash and checking the extension of the pathname fixes all three cases while leaving page redirects untouched:

const [pathname] = req.url.split(/[#?]/) as [string, ...string[]];
const looksLikeAsset = !!path.extname(pathname);

With that change, in the same repro, the three failing URLs return 200 and /mysite/docs/intro still redirects to /mysite/docs/intro/.

Your environment

  • Public source code: N/A — repro steps above, from a fresh create-docusaurus site
  • Public site URL: N/A — local docusaurus serve
  • Docusaurus version used: 3.10.2, also reproduced on main (4.0.0)
  • Environment name and version: Node.js v24.21.0
  • Operating system and version: macOS 15

Self-service

  • I'd be willing to fix this bug myself.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugAn error in the Docusaurus core causing instability or issues with its executionstatus: needs triageThis issue has not been triaged by maintainers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions