Skip to content

Fix build failure when frontend_path is set without prerendering - #7044

Merged
masenf merged 5 commits into
mainfrom
claude/happy-brown-ajf67r
Sep 9, 2026
Merged

Fix build failure when frontend_path is set without prerendering#7044
masenf merged 5 commits into
mainfrom
claude/happy-brown-ajf67r

Conversation

@masenf

@masenf masenf commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Description

Fixes a FileNotFoundError that occurs when running reflex run --env prod or reflex export with frontend_path configured and route prerendering disabled (REFLEX_SSR=false).

Root cause: When prerendering is disabled, the static output directory structure is not created with the frontend_path prefix. The build process attempted to move files into a non-existent prefix directory, causing the failure.

Solution: Explicitly create the prefix directory before attempting to relocate static files into it. This ensures the directory exists regardless of whether prerendering created it.

Changes

  1. reflex/utils/build.py: Modified the build() function to create the prefix directory before moving files, and simplified the file movement logic to use the pre-computed prefix_dir variable.

  2. tests/units/utils/test_build.py:

    • Extracted common test setup into _patch_build() helper to reduce duplication
    • Extracted static file creation into _write_static_output() helper
    • Added test_build_relocates_static_output_without_prerendered_prefix_dir() to verify files are correctly relocated when prerendering is off
    • Added test_build_merges_static_output_into_prerendered_prefix_dir() to verify prerendered output is preserved when merging with non-prerendered assets
  3. news/+frontend-path-noprerender-build.bugfix.md: Added changelog entry documenting the fix.

Test Plan

Added comprehensive unit tests covering both scenarios:

  • Static output relocation when the prefix directory doesn't exist (prerendering off)
  • Merging of static output into an existing prerendered prefix directory

All existing tests continue to pass.

https://claude.ai/code/session_01UwbNDEaQNGWeHWS8nxsURd

Review in cubic

… output

When frontend_path is set, build() moves every child of .web/build/client
into .web/build/client/<frontend_path>/. With route prerendering enabled,
React Router already emits the prerendered HTML under that prefix, so the
target directory exists by accident. With prerendering disabled
(REFLEX_SSR=false) nothing creates it: os.rename fails, shutil.move falls
back to copy2, and opening the destination raises FileNotFoundError,
crashing `reflex run --env prod` and `reflex export`.

Create the prefix directory up front so the relocation no longer depends
on prerendering. The existing skip for the prefix's first segment keeps
the prerendered output merging in as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwbNDEaQNGWeHWS8nxsURd
@masenf
masenf requested a review from a team as a code owner September 4, 2026 18:58
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwbNDEaQNGWeHWS8nxsURd
@codspeed-hq

codspeed-hq Bot commented Sep 4, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 3.18%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 39 untouched benchmarks
⏩ 8 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
test_var_access[mutable_dict] 47 ms 45.5 ms +3.18%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing claude/happy-brown-ajf67r (a0480cc) with main (5d9724e)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps

greptile-apps Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the build failure is covered by focused regression tests and no outstanding defect remains.

Summary

  • Uses PurePosixPath so configured URL paths work on Windows.
  • Validates frontend path segments against POSIX and Windows path semantics.
  • Adds regression coverage for relocation, prerendered-output merging, and unsafe path segments.
  • Adds changelog fragments for both affected packages.

Comment thread reflex/utils/build.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread reflex/utils/build.py
frontend_path is a URL prefix, but it also names the directory below
.web/build/client that the production build is relocated into (build.py)
and served from (exec.py). A ".." segment would move the built frontend
outside the build output, and since path_ops.mv removes existing
destinations, could overwrite neighboring files.

Validate this once in Config._normalize_paths so every consumer can trust
the value, rather than re-checking at each filesystem use.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwbNDEaQNGWeHWS8nxsURd
…ndows

PosixPath cannot be instantiated on Windows, so the prefix relocation in
build() raised UnsupportedOperation there for any app with frontend_path
set. The value is only used for its parts and to join onto static_dir,
which PurePosixPath supports on every platform.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwbNDEaQNGWeHWS8nxsURd
Comment thread reflex/utils/build.py
The previous guard only rejected ".." between forward slashes. On Windows
a backslash is also a separator, so "..\\escaped" still traversed out of
the build output, and a drive-letter or rooted segment such as "D:other"
or "\\" makes pathlib replace the base path entirely.

Validate each slash-delimited segment with PureWindowsPath: it must have
no anchor (drive or root) and parse to exactly itself, which rules out
backslashes, drive prefixes, UNC forms, and ".". Bare ".." is rejected
explicitly since it parses to itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwbNDEaQNGWeHWS8nxsURd
@masenf
masenf merged commit e3e39a8 into main Sep 9, 2026
111 checks passed
@masenf
masenf deleted the claude/happy-brown-ajf67r branch September 9, 2026 17:39
masenf pushed a commit that referenced this pull request Sep 11, 2026
Builds the frontend_path + REFLEX_SSR=false combination the changelog names.
Both reflex export and reflex run --env prod fail on 0.9.10.post2 with exactly
the documented FileNotFoundError and succeed on 0.9.11a1, and the resulting prod
deployment works end to end in a browser under the sub-path — state round-trip,
client-side routing, reload and deep link.

Probing the same deployment with curl shows every route but / is answered with
HTTP 404 while serving the correct SPA document (FINDING-037). A four-way matrix
shows the trigger is REFLEX_SSR=false rather than frontend_path, and that the
previous stable does the same, so it is pre-existing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167TFRX1CXqwGK8uh7DBE7c
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.

3 participants