Skip to content

fix: in sortRoutePaths: sort files alphabetically#3769

Merged
bartlomieju merged 3 commits into
freshframework:mainfrom
will-weiss:linux-filesorting-bugfix
Apr 21, 2026
Merged

fix: in sortRoutePaths: sort files alphabetically#3769
bartlomieju merged 3 commits into
freshframework:mainfrom
will-weiss:linux-filesorting-bugfix

Conversation

@will-weiss
Copy link
Copy Markdown
Contributor

@will-weiss will-weiss commented Apr 11, 2026

The fix for the bug described was found with the assistance of Claude Opus 4.6. The analysis presented is from the AI, not my own, but I can confirm that the workaround it presented (which it said was based on its findings) did work for my use case.

What I observed

For our fresh 2.2.0 project I observed that on github actions builds middleware defined in routes/app/_middleware.tsx were not running before the handler defined in routes/app.tsx after vite build. This was not the same behavior I observed when testing locally on my Mac.

I pulled down the generated /_fresh directory from github actions and instructed Claude to look to see if there were any differences in those files generated during the github actions build and those generated by running the same commands on my mac.

From Claude Opus 4.6

@fresh/core's sortRoutePaths function has a bug on lines with return charA <
  charB ? 0 : 1 — when charA < charB, it returns 0 (equal) instead of -1 (a before b). This
  makes the comparator asymmetric: compare(a, b) can return 0 while compare(b, a) returns 1.

  On macOS, Deno.readDir returns files alphabetically, which happens to produce the correct
  final sort even with the broken comparator. On Linux (CI), Deno.readDir returns files in
  hash-table order. The stable TimSort algorithm + inconsistent comparator + different initial
  ordering = /app/_middleware ends up at position 112 instead of position 4, so the auth
  middleware never runs for /app routes.

  Fix: scripts/fix_fresh_route_order.ts re-sorts the fsRoutes array in
  _fresh/server/server-entry.mjs after the build using the correct comparator. It's wired into
  deno task build so it runs automatically on both local and CI.

The referenced workaround script scripts/fix_fresh_route_order.ts overwrites the route ordering in the generated _fresh/server/server-entry.mjs file after that has been built by vite build. While I have not evaluated the contents of that script line by line, I did scan it and it does seem to be doing what is suggested and I can confirm that it did fix the issue, suggesting that the overall analysis is sound.

Closes #3773

@will-weiss will-weiss changed the title fix in sortRoutePaths: sort files alphabetically fix: in sortRoutePaths: sort files alphabetically Apr 11, 2026
@will-weiss will-weiss force-pushed the linux-filesorting-bugfix branch 3 times, most recently from 8809231 to 9fb6b42 Compare April 12, 2026 00:51
@will-weiss will-weiss force-pushed the linux-filesorting-bugfix branch from 9fb6b42 to 36e06ef Compare April 12, 2026 01:04
Plain `<` comparison is correct for route paths (ASCII) and preferable
to localeCompare which would reintroduce platform-dependent ordering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@bartlomieju bartlomieju enabled auto-merge (squash) April 21, 2026 17:03
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju merged commit ecc4285 into freshframework:main Apr 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Incorrect route sorting order for mixed static and dynamic paths

2 participants