Build Diagnostics

Reference for SPIDERLY### diagnostic codes emitted by Spiderly source generators when entity definitions violate a contract.

Overview

When an entity class violates a contract the source generators rely on — a missing base class, a malformed [ForeignKey], an ambiguous relationship, a broken [DisplayName] path — Spiderly emits a located Roslyn diagnostic at build time rather than crashing with CS8785 "generator failed to generate source".

Each diagnostic:

  • Has a stable SPIDERLY### ID (never reused, never renumbered).
  • Renders as a red squiggle in Visual Studio / Rider / VS Code on the offending class or property.
  • Appears in the build output with a clickable file and line.
  • Is parseable by CI logs and AI agents for automated fix suggestions.

Diagnostics are reported by the generator's SourceProductionContext, so they behave like any other compiler warning or error — you can suppress individual codes via <NoWarn> in the .csproj, treat warnings as errors, or filter them in CI output. Severity is Error for everything except SPIDERLY013 (Warning).

Diagnostic Reference

IDSeverityTitle
SPIDERLY001ErrorController type is not a discovered entity or DTO
SPIDERLY002ErrorMany-to-many entity requires exactly two [M2MWithMany] properties
SPIDERLY003Error[ForeignKey] references a property that does not exist
SPIDERLY004ErrorForeign key type does not match target primary key
SPIDERLY005ErrorForeign key is ambiguous — multiple convention matches
SPIDERLY006ErrorForeign key nullability does not match navigation property
SPIDERLY007Error[DisplayName] path references a property that does not exist
SPIDERLY008Error[DisplayName] path segment is not a many-to-one navigation
SPIDERLY009Error[DisplayName] navigation target entity not found
SPIDERLY010ErrorEntity missing required BusinessObject<T> / ReadonlyObject<T> base
SPIDERLY011ErrorController property type is not resolvable for client generation
SPIDERLY012ErrorOne-to-many back-reference missing [M2MWithMany]
SPIDERLY013WarningBackend folder not found under calling project
SPIDERLY014ErrorBlob property missing [AcceptedFileTypes] attribute

SPIDERLY001

Controller type is not a discovered entity or DTO.

A controller action takes or returns a class that isn't a Spiderly entity (inheriting BusinessObject<T> / ReadonlyObject<T>) and isn't in a namespace ending with .DTO. The generated Angular client would reference an undefined TypeScript type.

Fix: move the class into a namespace ending with .DTO, or make it inherit from a Spiderly entity base class.

SPIDERLY002

Many-to-many entity requires exactly two [M2MWithMany] properties.

An entity declared as a many-to-many join has zero, one, or more than two [M2MWithMany] attributes. A join needs exactly one on each side.

Fix: annotate each of the two navigation properties on the join entity with [M2MWithMany] pointing at the opposite side. See Relationships for a worked example.

SPIDERLY003

[ForeignKey] references a property that does not exist.

[ForeignKey(nameof(X))] on a navigation or scalar points at a member name that isn't declared on the entity.

Fix: correct the nameof(...) argument, or add the missing scalar/navigation property.

SPIDERLY004

Foreign key type does not match target primary key.

The FK scalar's type (e.g. int) doesn't match the type of the target entity's Id (e.g. long).

Fix: change the FK scalar to the target entity's Id type. The primary key type comes from the entity's BusinessObject<T> / ReadonlyObject<T> base.

SPIDERLY005

Foreign key is ambiguous — multiple convention matches.

Multiple scalar properties match the {NavigationName}Id convention for the same navigation, so the generator cannot pick a unique FK.

Fix: use [ForeignKey(nameof(ExplicitFkScalar))] on the navigation to disambiguate.

SPIDERLY006

Foreign key nullability does not match navigation property.

Either a [Required] navigation is paired with a nullable FK scalar, or an optional navigation is paired with a non-nullable FK scalar.

Fix: align them. [Required] Category Category must pair with non-nullable long CategoryId; optional Category Category must pair with nullable long? CategoryId.

SPIDERLY007

[DisplayName] path references a property that does not exist.

A segment of [DisplayName("A.B.C")] names a property that isn't declared on the corresponding entity.

Fix: correct the path, or add the missing property.

SPIDERLY008

[DisplayName] path segment is not a many-to-one navigation.

An intermediate segment of a [DisplayName] path must be a many-to-one navigation so the generator can follow the chain.

Fix: use only M2O navigations for intermediate segments. Scalars and collection properties are only valid as the final segment.

SPIDERLY009

[DisplayName] navigation target entity not found.

The entity type referenced by a [DisplayName] navigation segment is not discovered in the current project or any referenced project with a .Entities namespace.

Fix: ensure the target entity lives in a .Entities namespace and its project is referenced.

SPIDERLY010

Entity missing required BusinessObject<T> / ReadonlyObject<T> base.

Every Spiderly entity must inherit — directly or transitively — from BusinessObject<T> or ReadonlyObject<T>. The generators cannot resolve the entity's Id type otherwise.

Fix: add the appropriate base class. See Add New Entity.

SPIDERLY011

Controller property type is not resolvable for client generation.

A generated controller method references a navigation property whose target entity cannot be discovered, so the Angular autocomplete / dropdown method cannot be generated.

Fix: ensure the target entity exists in a .Entities namespace and its project is referenced.

SPIDERLY012

One-to-many back-reference missing [M2MWithMany].

An entity declares a one-to-many collection into a complex many-to-many join, but the join entity has no property annotated with a matching [M2MWithMany(nameof(...))] pointing back.

Fix: add [M2MWithMany(nameof(ThisCollection))] to the corresponding navigation on the join entity.

SPIDERLY013

Backend folder not found under calling project.

The file-emitting generators (Angular entities/controllers/validators/details/enums) walk up from the calling project to find a Backend folder as an anchor for writing output. They emit this warning and skip file emission if the folder can't be found.

Fix: ensure your backend project lives under a folder named Backend (or pass a custom name if your generator consumer supports it).

SPIDERLY014

Blob property missing [AcceptedFileTypes] attribute.

Every [BlobName] property must declare [AcceptedFileTypes("mime/type", ...)] with at least one MIME-typed value. There is no implicit default — the old images-only fallback has been removed so every blob property's upload whitelist is an explicit, auditable decision at the source level.

An attribute that contains only extension values (e.g. [AcceptedFileTypes(".pdf")]) also trips this because the generator filters to MIME-typed entries (values containing /) when emitting the server-side validator.

Fix: add [AcceptedFileTypes(...)] with one or more MIME types. Examples:

[BlobName]
[AcceptedFileTypes("image/jpeg", "image/png", "image/webp", "image/avif")]
public string ImageUrl { get; set; }

[BlobName]
[AcceptedFileTypes("application/pdf", ".pdf")]
public string PdfFile { get; set; }

Suppressing Diagnostics

To suppress a specific diagnostic project-wide, add it to <NoWarn> in the consuming project's .csproj:

<PropertyGroup>
  <NoWarn>$(NoWarn);SPIDERLY013</NoWarn>
</PropertyGroup>

Suppress at a single site with a #pragma:

#pragma warning disable SPIDERLY013
// ...code that triggers the diagnostic...
#pragma warning restore SPIDERLY013

Use sparingly — each diagnostic points at a real contract violation that will produce broken generated code.