Context
The daemon project uses <InvariantGlobalization>true</InvariantGlobalization> to reduce binary size (~28MB savings by stripping ICU culture data). This is incompatible with Discord.Net.
Problem
Discord's Guild object has a required preferred_locale field (always present, defaults to en-US). Discord.Net unconditionally maps this to a .NET CultureInfo in SocketGuild.Update:
new CultureInfo(PreferredLocale) // throws in invariant mode
When InvariantGlobalization=true, the runtime only supports CultureInfo.InvariantCulture. Any real locale like en-US throws CultureNotFoundException, which prevents guild data from loading. Without guild data, the channel cache is empty and all incoming messages are dropped as "Unknown Channel."
This is a known open issue in Discord.Net (#2704) with no library-side fix. There is no Discord.Net configuration to skip the CultureInfo construction — it is hardcoded.
Resolution
Disable InvariantGlobalization in src/Netclaw.Daemon/Netclaw.Daemon.csproj. This adds ~28MB to the self-contained binary (ICU data) but is required for Discord channel support.
The CLI (Netclaw.Cli) retains InvariantGlobalization=true since it does not load Discord.Net.
Why not alternative approaches?
PredefinedCulturesOnly: Still requires ICU data bundled; no meaningful size savings over full globalization.
- Patching Discord.Net: The
CultureInfo construction is in a hot path (SocketGuild.Update) called on every guild event. A fork would be a maintenance burden, and the upstream issue has been open since 2023 with no resolution.
- Runtime culture injection: Not possible in invariant mode — the runtime rejects all non-invariant cultures regardless of how they're constructed.
For future contributors
If you're optimizing binary size and consider re-enabling InvariantGlobalization, be aware this will break Discord channel support entirely. The daemon will connect to Discord's gateway but silently drop all messages because guild/channel data fails to load. The error appears as:
[ERR] Gateway: Error handling Dispatch (GUILD_AVAILABLE)
System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode.
en-US is an invalid culture identifier.
Followed by:
[WRN] Gateway: Unknown Channel (MESSAGE_CREATE Channel=...)
This setting cannot be changed until Discord.Net resolves #2704.
Context
The daemon project uses
<InvariantGlobalization>true</InvariantGlobalization>to reduce binary size (~28MB savings by stripping ICU culture data). This is incompatible with Discord.Net.Problem
Discord's Guild object has a required
preferred_localefield (always present, defaults toen-US). Discord.Net unconditionally maps this to a .NETCultureInfoinSocketGuild.Update:When
InvariantGlobalization=true, the runtime only supportsCultureInfo.InvariantCulture. Any real locale likeen-USthrowsCultureNotFoundException, which prevents guild data from loading. Without guild data, the channel cache is empty and all incoming messages are dropped as "Unknown Channel."This is a known open issue in Discord.Net (#2704) with no library-side fix. There is no Discord.Net configuration to skip the
CultureInfoconstruction — it is hardcoded.Resolution
Disable
InvariantGlobalizationinsrc/Netclaw.Daemon/Netclaw.Daemon.csproj. This adds ~28MB to the self-contained binary (ICU data) but is required for Discord channel support.The CLI (
Netclaw.Cli) retainsInvariantGlobalization=truesince it does not load Discord.Net.Why not alternative approaches?
PredefinedCulturesOnly: Still requires ICU data bundled; no meaningful size savings over full globalization.CultureInfoconstruction is in a hot path (SocketGuild.Update) called on every guild event. A fork would be a maintenance burden, and the upstream issue has been open since 2023 with no resolution.For future contributors
If you're optimizing binary size and consider re-enabling
InvariantGlobalization, be aware this will break Discord channel support entirely. The daemon will connect to Discord's gateway but silently drop all messages because guild/channel data fails to load. The error appears as:Followed by:
This setting cannot be changed until Discord.Net resolves #2704.