Skip to content

Stop optional TOML keys crashing, and name the key in config errors - #175

Merged
JordanMarr merged 2 commits into
JordanMarr:mainfrom
michaelglass:fix/toml-filters-optional-keys
Oct 19, 2026
Merged

JordanMarr merged 2 commits into
JordanMarr:mainfrom
michaelglass:fix/toml-filters-optional-keys

Conversation

@michaelglass

@michaelglass michaelglass commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Before

Leaving out an optional key crashed the CLI. A [filters] section with only include failed:

[filters]
include = [ "dbo/*" ]
System.Collections.Generic.KeyNotFoundException : The given key 'exclude' was not present in the dictionary.

So did [filters] with only exclude or only restrictions (the error names include), and [sqlhydra_query_integration] without provider_db_type_attributes.

After

In the TOML Before After commit 1 After commit 2
[filters] with only include KeyNotFoundException: The given key 'exclude' was not present in the dictionary. loads loads
[filters] with only exclude KeyNotFoundException: The given key 'include' was not present in the dictionary. loads loads
[filters] with only restrictions KeyNotFoundException: The given key 'include' was not present in the dictionary. loads loads
[sqlhydra_query_integration] without provider_db_type_attributes KeyNotFoundException: The given key 'provider_db_type_attributes' was not present in the dictionary. loads loads
no connection in [general] KeyNotFoundException: The given key 'connection' was not present in the dictionary. unchanged [general] is missing required key 'connection'.
cli_mutable = "yes" InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Boolean'. unchanged [general] key 'cli_mutable' should be a Boolean, but is a String.
include = "dbo/*" InvalidCastException: Unable to cast object of type 'System.Char' to type 'System.String'. unchanged [filters] key 'include' should be an Array, but is a String.
restrictions = { "Tables" = [ 1 ] } InvalidCastException: Unable to cast object of type 'System.Int64' to type 'System.String'. unchanged [filters.restrictions] key 'Tables' should be a String, but is an Integer.

Over-engineering?

Could drop the second commit that improves error messages. you tell me.


Spikes, for context: we also tried reading the file into typed classes with Tomlyn (on 0.17, on Tomlyn 2.10.1). They didn't help: on 0.17, Tomlyn converts types loosely (connection = true loads as "True") and has no required keys, so it needed a reflection checker doing the same job as this PR's Section.Cast at more than twice the parser changes. On 2.10.1, Tomlyn checks types and required keys itself, but its errors don't name the key (Expected String token but was Boolean.), and fixing that means parsing its message text, on top of a two-major-version upgrade. This PR gets strict types and clear messages without either.

@michaelglass michaelglass changed the title Read [filters] when include or exclude is left out Read optional TOML keys without crashing when they're left out Sep 29, 2026
@michaelglass michaelglass changed the title Read optional TOML keys without crashing when they're left out Make optional TOML keys optional by construction Sep 29, 2026
@michaelglass michaelglass changed the title Make optional TOML keys optional by construction Stop optional TOML keys crashing, and name the key in config errors Sep 29, 2026
@michaelglass
michaelglass force-pushed the fix/toml-filters-optional-keys branch from 803ae15 to 4e1165a Compare September 29, 2026 12:25
@michaelglass
michaelglass marked this pull request as ready for review September 29, 2026 12:27
A [filters] section with only one of include/exclude (or only
restrictions) threw KeyNotFoundException for the missing key. So did a
[sqlhydra_query_integration] section without provider_db_type_attributes.

A missing include or exclude now reads as an empty list, which filters
nothing. A missing provider_db_type_attributes now means true, the same
as a missing section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@michaelglass
michaelglass force-pushed the fix/toml-filters-optional-keys branch from 4e1165a to fe7ff7e Compare September 29, 2026 13:12
A missing required key threw a bare KeyNotFoundException, and a value of
the wrong type threw an InvalidCastException that did not say which key
was wrong.

Read the config through a Section, which knows its own name ("[general]",
"[filters.restrictions]") and replaces the Get and TryGet extensions on
TomlTable. When a required key is missing or a value has the wrong type,
the error names the section, the key and the TOML kinds, e.g.
"[general] key 'cli_mutable' should be a Boolean, but is a String."

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@michaelglass
michaelglass force-pushed the fix/toml-filters-optional-keys branch from fe7ff7e to cd7d4c3 Compare September 29, 2026 13:28
| _ -> failwith $"{name} key '{key}' should be {kind typeof<'T>}, but is {kind (value.GetType())}."

/// The value at `key`, or None when it is left out. Fails when the value has the wrong type.
member this.TryGet<'T>(key: string) : 'T option =

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the functionality change but I'm generally not so happy with these names. Alas.

@JordanMarr
JordanMarr merged commit 96b4347 into JordanMarr:main Oct 19, 2026
1 check passed
@JordanMarr JordanMarr mentioned this pull request Oct 19, 2026
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.

2 participants