Skip to content

Never let one property getter lose a whole OptionsDescription (#590) - #591

Open
jeremydmiller wants to merge 1 commit into
mainfrom
gh/harden-options-description
Open

Never let one property getter lose a whole OptionsDescription (#590)#591
jeremydmiller wants to merge 1 commit into
mainfrom
gh/harden-options-description

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #590.

OptionsDescription(object subject) builds a diagnostic view by calling arbitrary property getters on somebody else's configuration object. Any one of those getters can throw, and until now that lost the entire description — along with everything built on top of it.

Reported from the field as JasperFx/wolverine#3740: AzureServiceBusTransport.HostName threw a NullReferenceException for credential-based (managed identity) connections, so a monitored Wolverine service could never build its ServiceCapabilities snapshot, so CritterWatch never completed a handshake for it — permanently, since the same doomed read is retried on every batch.

What changed

  • Skip properties that cannot be read at all. Set-only properties (no getter → ArgumentException) and indexers (GetValue with no index arguments → TargetParameterCountException). Both are legal on a described type and neither is configuration data. Wolverine.Pulsar's PulsarTransport has a this[Uri] indexer, which alone was enough to make it undescribable.
  • Catch what a getter throws — including from the [ChildDescription], [DescribeAsStringArray] and [DescribeAsConfigurationState] branches — and record OptionsValue.Unreadable(...) in its place, with Value = "Could not be read -- <ExceptionTypeName>".
  • Exception type only, never the message. Descriptions get shipped to monitoring consoles and go to some length to keep secrets out (see the broker connection-summary redaction work); exception messages habitually quote the offending configuration value.

The per-property body moved into a readProperty(...) helper so the try/catch wraps every branch, with no behavior change for properties that read cleanly.

Tests

CoreTests/Descriptors/OptionsDescriptionTests.cs gains a describing_awkward_properties fixture: a throwing getter, a throwing [ChildDescription], an indexer, a set-only property, secret-in-the-exception-message, and still-serializable. Full CoreTests (485) and CommandLineTests (295) green locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RainvDHdde5JUAiGEPEgWw

)

An OptionsDescription is a diagnostic view built by calling arbitrary
property getters on somebody else's configuration object, so any one of
them can throw -- and losing the entire description over one bad property
is a terrible trade. Reported from the field as JasperFx/wolverine#3740,
where AzureServiceBusTransport.HostName threw a NullReferenceException for
credential-based connections and a monitored service could consequently
never build its ServiceCapabilities snapshot at all.

- Skip set-only properties and indexers, neither of which can be read via
  PropertyInfo.GetValue(subject) (ArgumentException /
  TargetParameterCountException). Wolverine.Pulsar's PulsarTransport has a
  this[Uri] indexer, which was enough to make it undescribable.
- Catch whatever a getter throws -- including from the [ChildDescription],
  [DescribeAsStringArray] and [DescribeAsConfigurationState] branches --
  and record OptionsValue.Unreadable(...) in its place.
- Report the exception TYPE only, never the message: descriptions get
  shipped to monitoring consoles and work hard to keep secrets out, and
  exception messages habitually quote the offending configuration value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RainvDHdde5JUAiGEPEgWw
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.

OptionsDescription should survive a property getter that throws, and skip indexers / set-only properties

1 participant