Skip to content

[PB Extension] Handle a missing lexicon without exposing full FW Lite - #2547

Merged
imnasnainaec merged 3 commits into
developfrom
pt/missing-lex-code
Aug 13, 2026
Merged

[PB Extension] Handle a missing lexicon without exposing full FW Lite#2547
imnasnainaec merged 3 commits into
developfrom
pt/missing-lex-code

Conversation

@imnasnainaec

@imnasnainaec imnasnainaec commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

When a project's stored lexicon code points at a lexicon that no longer exists, "Browse lexicon" left FW Lite in its unrestricted view with the project switcher enabled, letting the user navigate out of the embedded experience.

FW Lite only learned it was embedded in Paratext inside projectContext.setup(), which runs after the project opens. A missing lexicon makes openCrdtProject/openFwDataProject throw, so setup() never ran and inParatext stayed false. The CSS-gated restrictions still applied (data-paratext is on the DOM from first render), but the switcher's disabled={projectContext.inParatext} did not — that mismatch is the bug.

  • Set inParatext on the project context at construction, so the restriction holds while the project is loading and if it never loads. This also covers the case where resolveProjectType falls back to FwData for an unknown code and routes a Harmony project to the wrong view. The property is one-way: dev throws and prod logs on an attempt to turn it back off, mirroring how projectCode refuses re-assignment.
  • Ignore project selection in the sidebar while in Paratext, as defense in depth, with a dev-mode warning so an unexpected reach past the disabled dropdown is visible rather than silent.
  • Notify the user when a stored lexicon no longer resolves, instead of only logging before clearing it and reopening the selector.
  • Validate the lexicon code in displayEntry, which bypassed the existing check and handed a dead code straight to the browse URL.
  • Give the mini-lcm endpoint filter honest status codes: 404 for a missing project (FwLiteWeb mini-lcm routes return 500 instead of 404/400 for not-found and bad-request cases #2487) and 400 for its client-error paths (invalid project type, blank project code), which all defaulted to 500. The extension's validity check now treats 404 and 400 as definitive and everything else as transient. This matters because that check clears the user's stored lexicon, so it should act on a definitive answer rather than a backend fault — and a whitespace-only code reaches the blank-code branch, so 404 alone would have accepted it.

Test plan

Manual, with a Paratext project whose lexicon.lexiconCode setting names a lexicon that does not exist in FW Lite:

  • "Browse lexicon" shows an error notification naming the lexicon and opens the lexicon selector; the full FW Lite view never appears.
  • With a valid lexicon, browsing still opens the embedded view and the project switcher is disabled.
  • Stop FW Lite mid-session, then invoke "Browse lexicon": the stored lexicon code is retained (not cleared) and the failure is logged.
  • A whitespace-only lexicon.lexiconCode is rejected by the project-settings validator.

Automated: svelte-check clean, viewer unit tests pass (159), extension lint/build clean, FwLiteWeb builds. Viewer browser tests were not run locally (Playwright chromium not installed); they don't touch this code, but CI covers them.

Fixes #2440

Considered and rejected

Rendering a dedicated "lexicon not found" state in DotnetProjectView instead of the current toast-plus-ViewErrorBoundary path. It reads better, but it's a UX change beyond this bug, and the viewer's no-try/catch-around-async rule makes it more than a small diff. Worth a follow-up if the boundary message proves confusing.

🤖 Generated with Claude Code

When a project's stored lexicon code pointed at a lexicon that no longer
exists, "Browse lexicon" left FW Lite in its unrestricted view with the
project switcher enabled.

FW Lite only learned it was embedded in Paratext inside
`projectContext.setup()`, which runs after the project opens. A missing
lexicon makes `openCrdtProject`/`openFwDataProject` throw, so `setup()`
never ran and `inParatext` stayed false. The CSS-gated restrictions still
applied (`data-paratext` is on the DOM from first render), but the
switcher's `disabled={projectContext.inParatext}` did not, so the user
could navigate to `/project/<code>` and out of the embedded view.

- Set `inParatext` on the project context at construction, so the
  restriction holds while the project loads and if it never loads.
- Ignore project selection in the sidebar while in Paratext.
- Notify the user when a stored lexicon no longer resolves, instead of
  only logging before clearing it and reopening the selector.
- Validate the lexicon code in `displayEntry`, which bypassed the
  existing check and handed a dead code straight to the browse URL.
- Return 404 rather than 500 for a missing project from the mini-lcm
  routes, so clearing the user's lexicon choice is driven by a definitive
  answer and not by a transient backend fault (#2487).

Fixes #2440

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📙 Platform.Bible labels Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: af02ad07-57f6-48b1-8530-cea8a09fa8aa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: af43cc75-8ea3-4f8a-93e3-d75a19375f91

📥 Commits

Reviewing files that changed from the base of the PR and between 8d27bbb and 167dab0.

📒 Files selected for processing (7)
  • backend/FwLite/FwLiteWeb/Routes/MiniLcmRoutes.cs
  • frontend/viewer/src/DotnetProjectView.svelte
  • frontend/viewer/src/project/ProjectSidebar.svelte
  • frontend/viewer/src/project/project-context.svelte.ts
  • platform.bible-extension/contributions/localizedStrings.json
  • platform.bible-extension/src/main.ts
  • platform.bible-extension/src/utils/project-manager.ts

📝 Walkthrough

Walkthrough

The changes add explicit project route error statuses, separate Paratext mode from project setup, block project switching in Paratext, and improve recovery when a stored lexicon code is no longer valid.

Changes

Project and lexicon selection handling

Layer / File(s) Summary
Explicit project route errors
backend/FwLite/FwLiteWeb/Routes/MiniLcmRoutes.cs
Invalid project requests return HTTP 400 problem responses. Missing projects return HTTP 404 problem responses.
Paratext project context guard
frontend/viewer/src/project/project-context.svelte.ts, frontend/viewer/src/DotnetProjectView.svelte, frontend/viewer/src/project/ProjectSidebar.svelte
Paratext mode is initialized separately, cannot be disabled after activation, and prevents project selection while embedded in Paratext.
Invalid lexicon recovery
platform.bible-extension/src/main.ts, platform.bible-extension/src/utils/project-manager.ts, platform.bible-extension/contributions/localizedStrings.json
Lexicon validation handles only HTTP 400 and 404 as invalid selections, reports discarded codes, and opens the selector when required.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: hahn-kev

Poem

I’m a rabbit guarding the project gate,
No Paratext switches while embedded state.
A lost lexicon gets a message bright,
Then the selector hops into sight.
Errors wear status codes neat—
Change complete, with carrot treat!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: handling missing lexicons without exposing unrestricted FW Lite.
Description check ✅ Passed The description directly explains the missing-lexicon bug, implementation changes, validation behavior, and test results.
Linked Issues check ✅ Passed The changes satisfy issue #2440 by showing an error, reopening the selector, and preventing unrestricted FW Lite navigation.
Out of Scope Changes check ✅ Passed The changes support the missing-lexicon fix and its required validation, embedding-state, navigation, notification, and HTTP status behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pt/missing-lex-code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@imnasnainaec imnasnainaec self-assigned this Aug 11, 2026
@argos-ci

argos-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Aug 13, 2026, 12:33 PM
e2e (Inspect) ✅ No changes detected - Aug 13, 2026, 12:41 PM

- Return 400 for the mini-lcm filter's other client-error paths (invalid
  project type, blank project code), which still defaulted to 500, and
  fix the garbled "Invalid project {type} type" message.
- Treat 400 as well as 404 as a definitive "this code can't resolve" in
  the extension's validity check. A whitespace-only lexicon code reaches
  the blank-code branch, so a 404-only check would have accepted it.
- Make `inParatext` one-way: dev throws and prod logs on an attempt to
  turn it back off, mirroring how `projectCode` refuses re-assignment.
- Warn in dev when a project selection is ignored in Paratext, so an
  unexpected reach past the disabled dropdown is visible rather than
  silent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@imnasnainaec
imnasnainaec marked this pull request as ready for review August 12, 2026 13:28
Comment thread frontend/viewer/src/project/ProjectSidebar.svelte Outdated
Comment thread backend/FwLite/FwLiteWeb/Routes/MiniLcmRoutes.cs

@hahn-kev hahn-kev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks good to me, Looking at how project-context is created I think I want to refactor it, but that's out of scope of this PR.

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

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📙 Platform.Bible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P.B ext] "Browse lexicon" mishandles invalid lexicon code

2 participants