errors-and-exceptions
Skill1 starsChanged 6 days agoMITView on GitHub
How Application reports not found and invalid input with exceptions, and how the presentation layer turns them into responses. Use when a use case can fail, when adding a new error case, or when changing how errors reach the caller.
In this repository40 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- add-a-use-caseSkill
- api-conventionsSkill
- branches-and-pull-requestsSkill
- cancellationSkill
- ci-for-your-solutionSkill
- ci-pipelineSkill
- clean-architecture-layersSkill
- configuration-and-environmentsSkill
- coverageSkill
- csharp-house-styleSkill
- data-access-ef-coreSkill
- database-migrationsSkill
- docker-and-composeSkill
- docs-and-voiceSkill
- expose-a-use-caseSkill
- family-syncSkill
- health-checksSkill
- integration-testsSkill
- json-serializationSkill
- mapping-with-mapperlySkill
- mcp-inspectorSkill
- mediatorSkill
- optional-token-authSkill
- packages-and-dependenciesSkill
- pagingSkill
- presentation-integration-testsSkill
- releasesSkill
- sample-dataSkill
- security-findingsSkill
- serilogSkill
- telemetrySkill
- template-authoringSkill
- test-designSkill
- time-providerSkill
- unit-testsSkill
- validationSkill
- writing-a-skillSkill
- xml-docs-and-openapiSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 31
Test the not-found path in the handler tests with Should.ThrowAsync<NotFoundException>.
- Very specific: line 32
If you add a new exception type, map it in the presentation layer's error handler in the same change, and test the mapping.
- Very specific: line 33
Test that the handler logs an unexpected exception once, as Error, and logs nothing for the ones it maps (unit-tests).
- Distinctive: line 61
Check that a row exists and then update or delete it.
- Distinctive: line 62
Put a stack trace, SQL or exception type name in a message.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Errors and exceptions
The rule
Application signals failure by throwing; it never returns error codes or result objects.
| Situation | Thrown by | Exception |
| Input breaks a rule | ValidationBehaviour, from the validator | FluentValidation.ValidationException |
| Something referenced doesn't exist | The handler | NotFoundException (src/Application/Common/Exceptions/NotFoundException.cs) |
| Anything else | Wherever | Left alone; the presentation layer reports it as an unexpected error |
The presentation layer maps each exception to its own shape in one place (in a web API, an IExceptionHandler writing RFC 9457 problem details). Messages are written for the caller and never include stack traces or internal details.
LoggingBehaviour logs validation failures and not found as Information, because the caller got an answer. The presentation layer's handler logs anything unexpected as Error, with the exception, in the same place it reports it (serilog).
Steps
- For a missing entity, use the helpers rather than
throw new:NotFoundException.ThrowIfNull(result, EntityType.Movie);after a fetch, or after an update that returns the changed entity, ornullwhen no row matched.NotFoundException.Throw(EntityType.Review);when a delete changed no rows.NotFoundException.Throw(EntityType.Author);after an existence check. Only check first when the write itself can't tell you which thing is missing, such as a new review's author and movie.
- A new kind of entity needs a value in
EntityType(src/Application/Common/Enums/EntityType.cs). - Test the not-found path in the handler tests with
Should.ThrowAsync<NotFoundException>. - If you add a new exception type, map it in the presentation layer's error handler in the same change, and test the mapping. If the caller should see it as an answer rather than a fault, log it in
LoggingBehaviourtoo. - Test that the handler logs an unexpected exception once, as
Error, and logs nothing for the ones it maps (unit-tests).
Example
// src/Application/Reviews/Commands/UpdateReview/UpdateReviewHandler.cs
var review = await reviewsRepository.UpdateReview(request.Id, request.Stars, request.Text, cancellationToken);
NotFoundException.ThrowIfNull(review, EntityType.Review);
return review;// src/Application/Reviews/Commands/CreateReview/CreateReviewHandler.cs
if (!await authorsRepository.AuthorExists(request.AuthorId, cancellationToken))
{
NotFoundException.Throw(EntityType.Author);
}Throw is marked [DoesNotReturn] and ThrowIfNull is marked [NotNull], so the compiler knows the value isn't null afterwards and nullable warnings stay quiet.
Don't
- Return
null,falseor an empty result to mean "not found" from a handler. - Catch exceptions in a handler to turn them into something else.
- Introduce a
Result<T>type. We use exceptions on purpose. - Check that a row exists and then update or delete it. That's two trips and a race; let the write tell you.
- Put a stack trace, SQL or exception type name in a message.
Check
dotnet test --filter "FullyQualifiedName~NotFound|FullyQualifiedName~ExceptionHandler"Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

