Fix the crash on the first logged line of a session - #308
Conversation
LoggingRepository shares its settings into a StateFlow with stateIn, and
CoroutineStart.DEFAULT means that sharing coroutine is dispatched, not started
in place. It ran on an IO thread while the constructor was still assigning
properties, and its first act - clearing the map of open loggers, which was
declared after the settings flow - dereferenced a map that was still null. The
NPE killed the coroutine, so the settings were never published, and every line
the game logged after that hit `error("Attempted to print log before settings
were loaded")` and took the client down. The reports come in on the first real
log call of a session: WraythClient buffers lines until <app> names the
character, then replays them, so the whole connection dies at login.
Declare the map before the flow so it exists before anything is launched, and
seed stateIn with the settings as they stand instead of null - the config store
is a StateFlow with a default, so there is always a value to read - so a line
arriving ahead of the first emission logs under the current settings rather
than throwing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WWiQAWnC8ZUoqQvwhrfvYS
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: 5 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 6 reviews per hour. 📝 WalkthroughWalkthroughThe change centralizes client log-settings conversion and initializes ChangesLogging initialization
Merge Risk: ⚪ Minimal · up to The PR makes a localized logging initialization change and adds regression coverage; no actionable merge-blocking risk remains beyond normal checks and review. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Fixes the production crash
IllegalStateException: Attempted to print log before settings were loaded(DESKTOP-3W, desktop@3.1.0).Root cause
LoggingRepositorydeclared its settings flow before the map that flow uses:stateInwithSharingStarted.Eagerlylaunches withCoroutineStart.DEFAULT— dispatched, not started in place. The sharing coroutine ran on an IO thread while the constructor was still executing, and its first act (clearing open loggers on the initial emission) dereferencedloggerswhile it was still null. The NPE killed the sharing coroutine for good, sologgingSettings.valuestayed at itsnullseed forever and every line the game logged afterwards hiterror("Attempted to print log before settings were loaded"), taking the client down.That is why it lands at login rather than at startup:
WraythClientbuffers log lines until the<app>event names the character, then replays them (WraythClient.kt:403→:1080), so the first real call into the repository is the one that kills the connection.The fix
loggersbeforeloggingSettings, so it is assigned before anything is launched — that also gives a real happens-before edge rather than just luckier ordering.stateInwithclientSettingRepository.getLogSettings()instead ofnull. The config store is aMutableStateFlowwith a default, so there is always a value to read; a line arriving ahead of the first emission now logs under the current settings instead of throwing. Theerror(...)is gone — a logging hiccup should never be fatal.ClientSettingRepository.getLogSettings(), sharing the mapping withobserveLogSettings().Verification
LoggingRepositoryTestcovers both halves. Reverting justLoggingRepository.ktreproduces the original failures exactly:Both pass with the fix, and
./gradlew check -PiosSkip=true -PlintSkip=trueis green.🤖 Generated with Claude Code
https://claude.ai/code/session_01WWiQAWnC8ZUoqQvwhrfvYS
Summary by CodeRabbit
Bug Fixes
Tests