Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Server pages load twice on the server (`?pick=default` and the plain file), so their data GETs return 405

Closed
#16 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@brenelz is already working on this.

Since Sep 25, 2026.

  • #17 by @brenelz — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript, vite

Research direction

Look at the file-routing plugin's manifest generation in the SSR environment, specifically how it imports server pages with ?pick=default. Examine the interaction with @solidjs/vite-plugin's server-function handler, which imports the plain file. The fix likely involves modifying the import logic in filesystem-routing or coordinating with the Vite plugin to avoid duplicate module instances. Start by understanding the module resolution in vite.config.ts and the resulting server bundle.

Written by the indexing model from the issue text.

Description

Describe the bug

With fileRoutes({ serverComponents: true }), a server page's route file is imported twice in the SSR environment:

  • The manifest imports it as src/routes/x.tsx?pick=default, which is the eager ref for server: true pages.
  • @solidjs/vite-plugin's server-function handler imports the plain src/routes/x.tsx, because the file contains "use server".

These are two module instances, and both run registerServerReference("<id>", fn) with the same id. In the production server bundle it shows up as two registrations:

var serverFunction_1$6 = registerServerReference("StoriesLayout-3c228249", async function StoriesLayout(_args) { ...   // from ?pick=default
var serverFunction_1$1 = registerServerReference("StoriesLayout-3c228249", async function StoriesLayout(_args) { ...   // from the handler's import

The second registration replaces the first in @solidjs/web's registry. @solidjs/router's fs adapter wraps the page in query(), which declares the function GET through GET(reference). That grant is bound to the first registration. declaresRead(id) checks the grant against the current registration, so it's false, and every client-side call to the page fails:

GET /_server/data/StoriesLayout-3c228249?args=... -> 405 Method Not Allowed (Allow: POST)

Server rendering works, since it calls the function directly. Client navigation to any server page returns 405, in both vite dev and the production build.

Your Example Website or App

I reproduced this in a small stories app (one server layout and two server pages), in both dev and build, by removing the workaround plugin. The setup below is the same configuration cut down to one page. I haven't run that cut-down version on its own.

Steps to Reproduce the Bug or Issue

Versions: [email protected], @solidjs/[email protected], @solidjs/[email protected], @solidjs/[email protected], [email protected].

vite.config.ts:

plugins: [
  solid({ start: {}, ssr: true, serverFunctions: { components: true } }),
  fileRoutes({ serverComponents: true })
]

src/router.ts:

import { pageRoutes } from "virtual:file-routes";
import { createRouter } from "@solidjs/router";
import { fileRoutes } from "@solidjs/router/fs";
export const Router = createRouter({ routes: fileRoutes(pageRoutes) });

src/routes/index.tsx is a client page with <a href="/about">About</a>. src/routes/about.tsx is a server page:

export default async function About() {
  "use server";
  return () => <p>About</p>;
}

(src/app.tsx renders <Router>. It also calls enableRichArguments(), to get past a separate router bug where search: undefined fails JSON argument encoding.)

  1. Run vite build and look in dist/server/server.js. registerServerReference("About-...") appears twice.
  2. Start the server and load /, then click "About".
  3. GET /_server/data/About-... returns 405. The same happens under vite dev.
Expected behavior

Each server page should have exactly one module instance on the server, so the function the router declares GET is the one the handler dispatches to. Some possible fixes:

  • filesystem-routing: in server environments, give server-page refs the plain module id instead of ?pick=default. Picking gains nothing for a module the handler loads in full anyway.
  • @solidjs/vite-plugin: have the handler manifest reuse the ?pick= id for modules the file-routes manifest already imports.
  • @solidjs/web: make a second registerServerReference for an id that already has a different function an error, or at least a dev warning. Today it silently replaces the first, which is why this surfaces as an unexplained 405.

A local workaround that fixes both dev and build is a Vite plugin, limited to the ssr environment, that strips ?pick= from src/routes/ imports in resolveId (order: "pre"). The client keeps its picked, code-split modules.

Platform
  • OS: macOS 15 (Darwin 24.3.0)
  • Browser: Chromium 149 (headless, Playwright)
  • Versions: as above, Node 24.21.0
Dominant language
TypeScript
Stars
20
Forks
5
Avg merge
5d 22h
Merged PRs (30d)
8

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from solidjs/filesystem-routing

All issues in solidjs/filesystem-routing

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.