Skip to content

feat: a fault keeps the exception that caused it, for the log and never the problem - #89

Merged
CaffeinatedCoder merged 2 commits into
release/2.3.0from
feat/fault-cause
Oct 28, 2026
Merged

CaffeinatedCoder merged 2 commits into
release/2.3.0from
feat/fault-cause

Conversation

@CaffeinatedCoder

Copy link
Copy Markdown
Owner

Closes #84

Problem

A caught exception was lost on the way to a Fault<TFault>. The MapError that turns it into the fault an endpoint answers dropped it, so a log of the refusal could not say what failed underneath (decision 52).

Change

  • Core: Fault<TFault>.Cause, set by Fault.Of(reason, detail, cause) and the constructor of the same shape; Of(reason, detail, cause) on Fault<T1, T2> and Fault<T1, T2, T3>. WithRule and with keep it; a null cause is refused. Equality and the hash code are written by hand over the reason, detail and rule, so the cause takes no part; ToString() prints as 2.2 did.
  • AspNetCore: FaultProblem<TFault>.Cause, and IFaultFeature.Cause as a default member, so a host's own implementation still builds. Nothing of the cause is written into the problem.
  • Docs: the AspNetCore README's new "What failed underneath" (two compiled samples), the core README's fault section, the changelog, the option-result note; the roadmap item goes.
  • Probe corpus: the two C03 seeds that patch FaultProblem.cs and TypeKitHttpResultExtensions.cs are regenerated against the new source. The private Problem() helper stays the composed overloads' alone, so each-error-own-set still breaks composed faults only.

Tests

  • FaultTests, ComposedFaultTests: the cause is kept, refused when null, kept by WithRule and with, and left out of equality, hashing and printing.
  • FaultResponsePartsTests: over the four Fault<TFault> overloads and a composed one, the cause reaches IFaultFeature.Cause and the problem has exactly the members a fault without a cause writes, naming neither the exception's type nor its message.
  • Seeded and caught: equality over the cause (2 tests fail), a dropped cause in ToHttpResult (6), the cause's message written into the problem (5).
  • Full suite: 18,228 passed. Package validation against 2.2.0 passes for both packages. prober seeds --probe C03ComposedProbe: 5 of 5 seeds caught.
  • Not run here: the seeds of the other probes whose footprint includes the changed files (seeds --all before the tag).

🤖 Generated with Claude Code

…er the problem

A caught exception was lost on the way to a Fault<TFault>: the MapError that turns it into the fault an
endpoint answers dropped it, so a log of the refusal could not say what failed underneath (decision 52).

- Fault<TFault>.Cause, set by Fault.Of(reason, detail, cause) and the constructor of the same shape, and
  Of(reason, detail, cause) on Fault<T1, T2> and Fault<T1, T2, T3>. WithRule and `with` keep it. A null
  cause is refused where one is given.
- Equality and the hash code are the reason's, the detail's and the rule's, written by hand so the cause
  takes no part; ToString prints as 2.2 did.
- AspNetCore: FaultProblem<TFault>.Cause, and IFaultFeature.Cause as a default member, so a host's own
  implementation still builds. The problem's members are the same with a cause as without one.
- READMEs (core, and AspNetCore's "What failed underneath" with compiled samples), changelog, the
  option-result note; the roadmap item goes.
- The C03 seeds are regenerated against the new source. The private Problem() helper stays the
  composed overloads' alone, so each-error-own-set still breaks composed faults only.

Proved by seeding: equality over the cause fails two tests, a dropped cause in ToHttpResult six, and
the cause's message written into the problem five.

Closes #84

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CaffeinatedCoder CaffeinatedCoder added this to the 2.3.0 milestone Oct 28, 2026
@CaffeinatedCoder CaffeinatedCoder added enhancement New feature or request package/core Affects CodoMetis.TypeKit package/aspnetcore Affects CodoMetis.TypeKit.AspNetCore area/option-result Option, Result and their extensions labels Oct 28, 2026
The fault feature carries both NameWithheld (#96) and Cause; the changelog
keeps both entries and the roadmap drops both items; the two prober seeds
this branch edited are deleted, as #108 retired the prober.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CaffeinatedCoder
CaffeinatedCoder merged commit 2416b31 into release/2.3.0 Oct 28, 2026
8 checks passed
@CaffeinatedCoder
CaffeinatedCoder deleted the feat/fault-cause branch October 28, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/option-result Option, Result and their extensions enhancement New feature or request package/aspnetcore Affects CodoMetis.TypeKit.AspNetCore package/core Affects CodoMetis.TypeKit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant