Skip to content

Diagnostics

Every code the Hardened generators and build tasks raise.

Warnings become errors under ContinuousIntegrationBuild, so anything left unaddressed locally fails CI. Where a warning describes something you meant, silence it by id:

xml
<PropertyGroup>
  <NoWarn>$(NoWarn);HOAG030</NoWarn>
</PropertyGroup>

The framework's own docs/design/generator-diagnostics.md carries the long-form entry for each, with the message text and the fix.

Prefixes

PrefixRaised by
HOAGHandler binding: matching [Handler] classes to described services
HAUTHAuthorization
HRDRRouting
HRDVValidation
HRDWWeb handlers
HRDFTriggers and their adapters
HRDRMResponse models
HRDT[Throws<T>]
HRDSCAuthentication schemes
HRDOAThe code-first OpenAPI document
HOATThe OpenAPI description build task
HSMTThe Smithy description build task
HTPLThe hardened-web template's own project checks
HRDAWSHardened.Amz
VMValidationModules, whose constraints the validation generator compiles. VM1503: a [ValidateNested] target is not sealed and declares no polymorphism mode

HOAT and HSMT share one numbering: a number means the same thing under each, and a finding is reported under the prefix of the front end that read the description. A number that exists for one front end only leaves a gap in the other.

Handler binding

IdMeaning
HOAG001errorThe routing table generator failed
HOAG002errorThe description could not be parsed; the build task's message is passed through
HOAG010warningA handler was skipped because a parameter type did not resolve. Other handlers are unaffected
HOAG020errorAn operation declares a markup content type and names no view to render it
HOAG030warningA described service has no [Handler]. Its routes exist and fail at request time. NoWarn it in a project that ships contracts without implementations
HOAG031warningA [Handler] class names no described service in its base list. Usually a spelling mismatch. A base class beside the interface is fine
HOAG032warningA described handler carries a declaration read from a handler's own syntax, such as [RawResponse]. A described operation's signature is generated, so it compiles, reads as a commitment, and changes nothing. The contract says the same thing with the response's media type

Routing

IdMeaning
HRDR001errorTwo routes are ambiguous. Give them different paths
HRDR002errorUnsupported route token syntax
HRDR003errorA [RouteConstraint] method has the wrong signature. It must be static bool(ReadOnlySpan<char>)
HRDR004errorMore than one Hardened entry point in one assembly
HRDR005warningA route token binds no parameter
HRDR006warningNo routing generator is compiling this assembly's routes
HRDR007errorA service parameter binds from the request body
HRDR008errorMore than one routing generator is compiling this assembly
HRDR009errorMore than one parameter binds from the request body. The message names them and the ways out
HRDR010warningA parameter binds from the body of a request that carries none, on a GET, HEAD or DELETE

Validation

IdMeaning
HRDV001retiredRetired. It warned that a constraint on a handler parameter was not compiled; they are compiled now
HRDV002warningTwo validators claimed the same generated file
HRDV003warningA required member of a value type cannot be found missing, so [Required] there does nothing
HRDV004warningNested constraints are never reached
HRDV005errorA When or Unless on a parameter's constraint names a member of a model the parameter does not sit on
HRDV006warningConstraints are declared and nothing compiles them into a validator, so none is enforced. Reference Hardened.Validation.SourceGenerator

Web handlers

IdMeaning
HRDW002errorA handler binds both a form and a body
HRDW003errorA handler declares [Compress] more than once, on the method and on its class
HRDW004error[ServerSentEvents] on a handler that does not return IAsyncEnumerable<T>
HRDW005warningResponse caching is declared and no store is registered. Names the package and the module attribute
HRDW006error[Timeout] declares no budget. The budget must be positive; an unbounded handler declares none

Responses

IdMeaning
HRDRM003errorA response case is object or dynamic, so the dispatch would answer that case's status for every response
HRDRM004errorTwo cases at different statuses where one is assignable to the other
HRDT001errorA [Throws<T>] names a type with no [HttpStatus] and states no status of its own
HRDSC001warningAn authentication scheme attribute is not read where it was written

Authorization

IdMeaning
HAUTH001warningThe module carries [RequireAuthorization] and this handler declares nothing. <NoWarn> is the only lever: neither #pragma nor an .editorconfig severity affects a generator-reported diagnostic. Anything implementing IAuthorizeAttribute satisfies it, including attributes of your own

The code-first document

IdMeaning
HRDOA001error<HardenedOpenApiVersion> is not 3.0.0, 3.1.0 or 3.2.0
HRDOA002warningA streamed response under a document version with no itemSchema; the operation is described without a schema
HRDOA003warning[Enable<OpenApiDocumentPublishing>] sits on a module declaring no routes, so the document is empty
HRDOA004errorTwo handlers declare the same [Operation] id, so a generated client would have two methods with one name

The description build tasks

Shared between HOAT and HSMT.

NumberMeaning
001errorThe description file does not exist
002errorThe description could not be parsed
003errorThe description was declared as the wrong item kind
004errorA model or generated source the extract step should have written is missing. Delete the model directory and rebuild
005errorThe targets file was imported before the specs were declared. Move the <Import> below the item group
006warningThe reader had something to say, including what a degraded trait promises that the code does not enforce: a Smithy BigDecimal or BigInteger member narrowed to decimal, once per member, or scopes on an http scheme, which cannot carry them. NoWarn is the answer where the narrowing is meant
007errorA slice selected no operations
008warningA slice removed a schema that is still referenced; the reference degrades to JsonElement
009warningThe spec is sliced but its document is embedded whole, so the served description claims operations the application does not implement
015errorHSMT only. More than one PublishUrl or UiUrl
016errorUiUrl without PublishUrl
017errorSourceUrl without EmbedDocument
026warning$(HardenedResponseModel) is Standard, the throws mode's name before 0.19.0. The mode is unchanged; write Throws

The model-diagnostics pass

Problems any description can state that would generate C# which does not compile, reported against the document rather than as compiler errors in a generated file.

NumberMeaning
020warningA schema declares a property named like the schema itself, which C# forbids. The member is renamed; the wire name is unchanged
021warningTwo schemas generate one C# type name. Resolved automatically; rename one to choose the names yourself
022warningA oneOf with no discriminator whose branches cannot all be told apart by shape
023errorAn enum declaring both string and numeric values
024warningA declared keyword or trait the generator does not enforce
027errorA reference to something the description does not declare. Fatal, because a dangling $ref in a response silently degrades the success case to a bodyless one

025 is retired. It rejected two error responses at one status on one operation, which a valid Smithy model says routinely. A declared error is now named for the error or binds to a shipped wrapper, so two shapes at one status are two types either way. A model that used to be rejected now builds.

The document export

018, 019 and 028030, reported under the prefix of the front end that wrote the document.

NumberMeaning
018error<HardenedOpenApiOutput> is set and the assembly carries no served document. Code-first, add [Enable<OpenApiDocumentPublishing>] to the module declaring the routes
019errorThe project declares more than one served document, and one output path cannot express both
028errorThe output path's extension names no format. Use .json, .yaml or .yml
029error<HardenedOpenApiOutputVersion> is not 3.0.0 or 3.1.0
030warningThe file was lowered to a version with no itemSchema and the named operation streams. Once per operation

The Smithy CLI

IdMeaning
HSMT010errorThe Smithy CLI was not found. Install it, set $(HardenedSmithyCliPath), or commit an AST
HSMT011warningThe CLI is not the pinned version. An error under the pin, because a different CLI can produce a different AST from identical sources
HSMT012errorThe CLI refused the model. One error per finding
HSMT013warningWhat the CLI said without failing
HSMT014errorThe CLI exited cleanly and wrote no AST

The template

IdMeaning
HTPL001error--host aws-lambda with --response-model union. The union model needs net11.0 and the Lambda managed runtime is net8.0
HTPL002errorThe Kiota tool could not be restored, so the client cannot be generated
HTPL003errorThe Kiota tool and Microsoft.Kiota.Bundle disagree. Both versions move together

Triggers

IdMeaning
HRDF001errorHandlers use a trigger and no referenced runtime declares a module for it. Names the build property to set. The two ways to reach this are a missing runtime package and a provider that has no source of that kind
HRDF002warningTwo sources produce the same test façade method name, so only one can be reached. Rename one, or suppress to keep the collision
HRDF003infoAn adapter is bound to serve a trigger nothing in the project declares, so it ships in the deployment bundle unreachable. Usually the Hardened.Aws.Lambda meta package where individual adapters would do

Renumbered in 0.18

Codes moved so every number has one meaning per prefix, and so findings from a Smithy model stopped being reported as HOAT. If a NoWarn names an old code, update it:

HOAT003HOAT020, HOAT005HOAT021, HOAT010HOAT022, HOAT013HOAT024, HSPEC010025 under the front end's prefix, 010016 and 011017 under both prefixes, the silent-success HSMT012HSMT014, and the multiple-PublishUrlHSMT012HSMT015.

Released under the MIT License.