Skip to content

Add diagnostics for missing files requested by bare name (BL-16577) - #8171

Merged
andrew-polk merged 2 commits into
masterfrom
BL-16577-missing-file-diagnostics
Aug 6, 2026
Merged

Add diagnostics for missing files requested by bare name (BL-16577)#8171
andrew-polk merged 2 commits into
masterfrom
BL-16577-missing-file-diagnostics

Conversation

@JohnThomson

@JohnThomson JohnThomson commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What this is

Sentry issue 2699459502 ("Cannot Find File") is
dominated by requests for the bare name Checkbox.js. The card supposed no such file exists in
Bloom. It does: it's a Vite chunk in output/browser. A bundle we inject into a page at the server
root (Book.AddJavascriptFile) imports its sibling chunks by bare name, so they arrive at the
server with no directory — and they should always be found under BrowserRoot.

This PR does not fix that bug. I could not establish why the lookup fails on the affected
machines: the third lookup, GetFileDistributedWithApplication, is anchored to the application
folder, and the absolute browser root is already a factory search path, so on a valid install the
file is found regardless of anything here. What this adds is the instrumentation needed to find
out, plus a real weakness the investigation turned up.

Changes

Diagnostics. When a request that carries no directory misses, the Sentry detail message now
also reports BrowserRoot, whether the expected file is actually present, and the process's
current working directory. That distinguishes "the file is genuinely absent from that install"
from "we looked in the wrong place". Requests that carry a directory are unaffected.

The current-directory weakness. BloomFileLocator.BrowserRoot is a relative path, so testing
for a file with it resolves against the process's current working directory. Bloom doesn't control
that directory:

  • Windows File Explorer sets it to the folder of a double-clicked file — Bloom's own comment in
    Program.cs says so (BL-11004);
  • a shortcut's "Start in" value overrides it — this already bit us as BL-16230, which is why
    Program.NormalizeWorkingDirectory() exists;
  • any Open/Save dialog that doesn't set RestoreDirectory moves it mid-session, permanently —
    and BloomOpenFileDialog never set it.

Two lookups depended on it: BloomServer.LookForAFullPathToFile's browser-root preference (added
in 57893d0f1f for BL-15894) and BloomFileLocator.GetSearchPaths. Both now use a new
AbsoluteBrowserRoot, and the file dialogs no longer move the working directory.

Test double. PretendRequestInfo.GetQueryParameters() always returned an empty collection,
which made any request the server routes on a query parameter — such as the assetv one it adds to
every JS request — impossible to test at all. It now parses the query.

Risk to look at

The GetSearchPaths change is the one with teeth: that entry previously resolved to nothing
whenever the working directory wasn't the application folder, so making it work changes lookup
precedence
— the browser root now genuinely wins over the factory paths, which is what the
comment there always intended. The precedence tests in BloomFileLocatorTests cover this and pass.

Testing

BloomServerTests + BloomFileLocatorTests + BookStarterTests: 125 passed, 0 failed, stable
across repeated runs, before and after merging master.

Full-suite counts are not usable as a signal at the moment — four runs of one unchanged tree gave
135, 1, 32 and 62 failures. That is other worktrees sharing %TEMP% plus tests that mutate
process-wide state, not this branch. (My first attempt at a regression test here changed the
process's current directory and took out a different unrelated test on each run; it was rewritten
to assert the resolved path is rooted instead.)

Ref: https://issues.bloomlibrary.org/youtrack/issue/BL-16577

Devin review


This change is Reviewable

JohnThomson and others added 2 commits August 6, 2026 16:52
Sentry reports thousands of "Cannot Find File" events for a request whose
path is the bare name "Checkbox.js". That file is not missing from the repo
as the card supposed: it is a Vite chunk in output/browser. A bundle we
inject into a page at the server root (Book.AddJavascriptFile) imports its
sibling chunks by bare name, so they reach the server with no directory,
and they should always be found under BrowserRoot.

This does NOT fix that bug - we have not established why the lookup fails on
the affected machines. It adds the diagnostics needed to find out, and fixes
a real weakness the investigation turned up along the way.

Diagnostics: when a request that carries no directory misses, the Sentry
detail message now also reports BrowserRoot, whether the expected file is
actually there, and the process's current working directory. Ordinary
requests, which carry a directory, are unaffected.

Current-directory weakness: BloomFileLocator.BrowserRoot is a relative path,
so testing for a file with it resolves against the process's current working
directory. Bloom does not control that directory - Windows File Explorer
sets it to the folder of a double-clicked file, a shortcut's "Start in"
value can override it (BL-16230), and a file dialog that does not set
RestoreDirectory moves it mid-session. Two lookups did exactly that:
BloomServer.LookForAFullPathToFile's browser-root preference and
BloomFileLocator.GetSearchPaths. Both now use a new AbsoluteBrowserRoot, and
the file dialogs no longer move the working directory.

Also teaches PretendRequestInfo to parse query parameters. It always
returned an empty collection, which made any request the server routes on a
query parameter - such as the assetv one it adds to every JS request -
impossible to test at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread src/BloomExe/MiscUI/BloomOpenFileDialog.cs
@JohnThomson

Copy link
Copy Markdown
Contributor Author

[Claude Opus 5 (1M context)] Consulted Devin on 2026-08-06 up to commit 33e01b80d1ea273d1322890dd69d354ae7dd63f0.

It found no bugs. It raised one thing worth a human look — whether turning on RestoreDirectory
for every file dialog changes where the one dialog that doesn't set its own starting folder opens
— which is its own thread.

Five further items were informational only, and I've folded the two that matter into the PR
description already: that making the browser-root search path absolute changes lookup precedence
(which is the intended effect, and the thing to review hardest), and that LocateFile now returns
rooted paths where a browser-root hit used to come back relative. The others noted that the new
test writes a scratch file into the shared output/browser folder (GUID-named, deleted in a
finally), that PretendRequestInfo.LocalPathWithoutQuery still keeps the query string unlike the
real one, and that the new diagnostics text is appended for any directory-less miss rather than
only JS ones.

CI reported no checks on this branch, and no other review bots have commented.

@JohnThomson
JohnThomson marked this pull request as ready for review August 6, 2026 22:25

@andrew-polk andrew-polk 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.

@andrew-polk reviewed 7 files and all commit messages, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on JohnThomson).

@andrew-polk andrew-polk 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.

Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on JohnThomson).

@andrew-polk
andrew-polk merged commit 23c1024 into master Aug 6, 2026
1 of 2 checks passed
@andrew-polk
andrew-polk deleted the BL-16577-missing-file-diagnostics branch August 6, 2026 22:55
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.

2 participants