Skip to content

fix: tolerate stripped Excel language headers + observe background tasks + dep bumps#111

Merged
logicallysynced merged 1 commit into
mainfrom
sharlayan-9-rebuild
May 12, 2026
Merged

fix: tolerate stripped Excel language headers + observe background tasks + dep bumps#111
logicallysynced merged 1 commit into
mainfrom
sharlayan-9-rebuild

Conversation

@logicallysynced
Copy link
Copy Markdown
Contributor

@logicallysynced logicallysynced commented May 12, 2026

Summary

Resolves an UnobservedTaskException reported by a downstream consumer (Chromatics, via Sentry) whose user runs a zh-TW Windows locale against what appears to be a CN-region FFXIV install. Lumina 7.4 rejects GetSheet<T>(Language.English) when the sheet's HeaderFile.Languages contains only Language.None; the throw fires inside MemoryHandler's fire-and-forget background task and was never observed, so the host AppDomain crashes at GC time on the default unhandled-task policy.

Two layers of fix, plus three bundled cleanups.

1. LuminaXivDatabaseProvider - tolerate missing per-language sheets

New private TryGetSheet<T>(GameData, Language, string) helper catches UnsupportedLanguageException and returns null. All three async methods now:

  • Treat the iteration source as required: English Action/Status sheets, default-language TerritoryType. If unavailable, log one NLog warning and return without populating the dictionary - no throw.
  • Treat JP/DE/FR (and the four PlaceName lookups for zones) as optional. Missing sheets contribute string.Empty to BuildLocalization instead of crashing.

BuildLocalization's four-string signature is preserved; CN/KR keep their Constants.UNKNOWN_LOCALIZED_NAME defaults.

2. MemoryHandler - observe the fire-and-forget tasks

Both Task.Run blocks in the constructor (resource resolution and signature resolution) now have .ContinueWith(OnlyOnFaulted) continuations that log the AggregateException via the existing Logger and raise OnException so consumers can surface it. Future exceptions in either background pipeline get observed and reported instead of becoming UnobservedTaskException at GC time.

3. Bundled in the same release

  • FCS submodule bump 78d04f840 → e8908dbe5 (15 commits - Update structs ×3, AgentHUD UI display mode bitfield, RaptureShellModule.ChangeChatChannel return-type fix, InventoryContextEvent update, misc ghidra tooling refactors). No integrity-test pin drift.
  • NLog + NLog.Schema bumped 6.1.2 → 6.1.3 (supersedes Dependabot PRs Bump NLog from 6.1.2 to 6.1.3 #109 and Bump NLog.Schema from 6.1.2 to 6.1.3 #110 - those can be closed).

Test plan

  • dotnet test - 179/179 passing
  • Debug build + deploy to Chromatics Build Dependencies (downstream consumer references the local DLL path)
  • Live verify against the affected zh-TW / CN-region install once the consumer picks up the new DLL - expected behaviour: a single NLog warning per missing-language sheet, no crash

🤖 Generated with Claude Code

Resolves an UnobservedTaskException downstream (Chromatics Sentry) caused
by Lumina.Excel.Exceptions.UnsupportedLanguageException thrown from inside
MemoryHandler's fire-and-forget background task on FFXIV installs whose
Excel sheets advertise only Language.None (observed on zh-TW Windows
locale with a CN-region client). The throw was happening during
ActionLookup.Resolve and was never observed, so the host AppDomain
crashed at GC time with the unhandled-task default policy.

Two layers of fix:

1. LuminaXivDatabaseProvider — tolerate missing per-language sheets.
   A new private TryGetSheet<T>(GameData, Language, string) helper catches
   UnsupportedLanguageException and returns null. All three async methods
   (GetActionsAsync, GetStatusEffectsAsync, GetZonesAsync) now:
     - Treat the iteration source (English Action/Status, default-language
       TerritoryType) as required. If it fails, log one NLog warning and
       return without populating the dictionary — no throw.
     - Treat JP/DE/FR (and PlaceName for zones) as optional. Missing sheets
       contribute string.Empty to BuildLocalization instead of crashing.
   BuildLocalization's four-string signature is unchanged; CN/KR keep
   their UNKNOWN_LOCALIZED_NAME defaults.

2. MemoryHandler — observe the fire-and-forget Tasks.
   Both Task.Run blocks in the constructor (resource resolution and
   signature resolution) now have a ContinueWith(OnlyOnFaulted) that
   logs the AggregateException via the existing NLog Logger and raises
   OnException so consumers can surface it. Any future exception in the
   background pipeline gets observed and reported instead of becoming an
   UnobservedTaskException at GC time.

Bundled in the same commit because they're related infrastructure work:
  - FCS submodule bump 78d04f840 → e8908dbe5 (15 commits — "Update structs"
    x3, AgentHUD UI display mode toggle bitfield, RaptureShellModule
    .ChangeChatChannel return-type fix, InventoryContextEvent update,
    misc ghidra import refactors).
  - NLog + NLog.Schema 6.1.2 → 6.1.3 (Dependabot PRs #109 / #110).

All 179 tests pass; no integrity-test pin drift from the FCS bump.

Version: 9.0.33 → 9.0.34.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@logicallysynced logicallysynced self-assigned this May 12, 2026
@logicallysynced logicallysynced merged commit fac1b5e into main May 12, 2026
3 checks passed
@logicallysynced logicallysynced deleted the sharlayan-9-rebuild branch May 12, 2026 06:57
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.

1 participant