You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ParsePhrase("") throws "Phrase must contain at least one chord (Parameter 'sequence')" from its own empty-input guard #128
The Phrase constructor (MusicalTypes.cs:~318) rejects an empty sequence, so this branch can never return. Every call with null, "" or whitespace throws:
ArgumentException: Phrase must contain at least one chord (Parameter 'sequence')
at Phrase..ctor
at KeybindingService.ParsePhrase KeybindingService.cs:182
Why it matters
The guard was clearly written to handle empty input in a controlled way, but the exception it produces names a parameter (sequence) that the caller never passed. A settings UI that parses a user's cleared keybinding field gets a confusing error that points inside the library. ParseChord validates its argument and throws with nameof(chordString), so the two parse methods behave differently.
Suggested fix
Pick one contract and implement it:
Throw new ArgumentException("Phrase string cannot be empty.", nameof(phraseString)), as ParseChord does. This is the minimal fix and doesn't change the API.
Or change the method to return Phrase? (or add TryParsePhrase) and return null for empty input.
Acceptance:ParsePhrase("") no longer throws from Phrase..ctor, and a test pins the chosen behaviour.
Priority: Low. Empty input already throws, but the exception names an internal parameter, so the only harm is a confusing error for a settings UI that parses a cleared field.
Area / suggested assignee:ParsePhrase in Services/KeybindingService.cs (:178-183), and the Phrase constructor in MusicalTypes.cs. Maintainer: @matt-edmondson.
Next steps: Pick a contract. The minimal option is to throw ArgumentException(..., nameof(phraseString)), matching ParseChord. If a nullable or TryParsePhrase API is wanted, that is an API change and needs the maintainer's call. Pin the chosen behavior with a test.
Activity
matt-edmondson commentedon Sep 27, 2026
Triage
ParsePhraseinServices/KeybindingService.cs(:178-183), and thePhraseconstructor inMusicalTypes.cs. Maintainer: @matt-edmondson.ParsePhrase. Normalize the key in the Note(NoteName) constructor as the string one does #126 targets Note(NoteName) doesn't uppercase before canonicalizing, so a chord built from NoteName "control" shows "Ctrl+S" but isn't equal to Chord.Parse("Ctrl+S") #121.Next steps: Pick a contract. The minimal option is to throw
ArgumentException(..., nameof(phraseString)), matchingParseChord. If a nullable orTryParsePhraseAPI is wanted, that is an API change and needs the maintainer's call. Pin the chosen behavior with a test.Generated by Claude Code