Skip to content

fix(Engine): don't crash on a duplicate key in a simple dictionary attribute - #2018

Merged
alexwarren merged 1 commit into
mainfrom
fix/duplicate-dictionary-key-crash
Aug 10, 2026
Merged

fix(Engine): don't crash on a duplicate key in a simple dictionary attribute#2018
alexwarren merged 1 commit into
mainfrom
fix/duplicate-dictionary-key-crash

Conversation

@alexwarren

Copy link
Copy Markdown
Contributor

Summary

Follow-up found while investigating a user report about the RunCommand.aslx library (from EightOne, a popular community library): loading a game that includes it fails with Error: Argument_AddingDuplicateWithKey, "to" instead of the friendly "Failed to load game due to the following errors" message.

Root cause

RunCommand.aslx's EditorScriptsScriptsRunCommandPrePositions template lists the "to" mapping twice:

"on"=on;"in"=in;"from"=from;"to"=to;"with"=with;"about"=about;"to"=to

That string is parsed as a simplestringdictionary editor <validvalues> attribute by SimpleStringDictionaryLoader.Load (src/Engine/GameLoader/AttributeLoaders.cs), which called QuestDictionary<string>.Add(key, value) for every entry with no duplicate check. Dictionary.Add throws ArgumentException ("Argument_AddingDuplicateWithKey") on a repeated key, and nothing between there and the WASM boundary (WasmEditorBridge.Initialise) catches that specific exception type as a normal load error — it falls into the generic catch (Exception ex) instead, and because WasmEditor is AOT-trimmed, ex.Message loses its resource string and becomes the bare, untranslated resource key.

This is a bug in that particular library file's data (a copy-paste duplicate), not something introduced by quest itself — but the engine crashing ungracefully on malformed dictionary data, with a cryptic message, is a real robustness gap: any third-party library (or hand-edited game) with a duplicate key in a simplestringdictionary/simpleobjectdictionary attribute hits the same crash today.

Fix

SimpleStringDictionaryLoader and its sibling SimpleObjectDictionaryLoader (same copy-pasted parsing loop, same latent bug) now check for a duplicate key before adding and record a normal, friendly load error instead — exactly mirroring the existing handling for a missing = a few lines above in the same method. The game still fails to load (the dictionary is genuinely ambiguous), but with a clear, actionable message pointing at the offending element/attribute instead of a raw exception.

Test plan

  • Added AttributeLoaderTests.cs with regression tests for both loaders: a duplicate key now produces a friendly WorldModel.Errors entry (Duplicate key '"to"' in dictionary element ...) instead of an uncaught exception — the assertion text matches the user's exact reported quoted-key format.
  • dotnet build --configuration Release (full solution) and dotnet test --configuration Release (294+ tests) both pass.

🤖 Generated with Claude Code

…tribute

A simplestringdictionary/simpleobjectdictionary attribute with a repeated
key (e.g. "to"=to;"to"=to in a third-party library's editor <validvalues>
template) threw an uncaught ArgumentException from Dictionary.Add during
load, instead of being recorded as a normal load error the way a missing
'=' already is a few lines above. In an AOT-trimmed build (WasmEditor)
this surfaced to the user as a raw, untranslated exception message like
"Argument_AddingDuplicateWithKey, "to"" instead of the friendly "Failed
to load game due to the following errors" list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@alexwarren
alexwarren merged commit 80c64e9 into main Aug 10, 2026
7 checks passed
@alexwarren
alexwarren deleted the fix/duplicate-dictionary-key-crash branch August 10, 2026 08:27
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