Skip to content

NullReferenceException in MulticastAttributeTask.IsAttributeInherited when inheriting attributes across assemblies #78

Description

@sharpcrafters-agent

Symptom

The compile-time task that propagates multicast attributes across assembly boundaries dereferences null and the
whole PostSharp project invocation fails:

System.NullReferenceException: Object reference not set to an instance of an object.
   PostSharp.Sdk.Extensibility.Tasks.MulticastAttributeTask.IsAttributeInherited(CustomAttributeDeclaration attribute, Boolean requiresInheritanceProperty)
   PostSharp.Sdk.Extensibility.Tasks.MulticastAttributeTask.IsAttributeInherited(CustomAttributeDeclaration attribute)
   PostSharp.Sdk.Extensibility.Tasks.MulticastAttributeTask.ImportCustomAttribute(IMetadataDeclaration target, CustomAttributeDeclaration customAttribute)
   PostSharp.Sdk.Extensibility.Tasks.MulticastAttributeTask.ProcessInheritedAttributesAcrossAssemblies(TypeDefDeclaration typeDef, ITypeSignature baseType)
   PostSharp.Sdk.Extensibility.Tasks.MulticastAttributeTask.ProcessInheritedAttributesAcrossAssemblies()
   PostSharp.Sdk.Extensibility.Tasks.MulticastAttributeTask.Execute()
   PostSharp.Sdk.Extensibility.Project.ExecutePhase(TaskPhase phase)
   PostSharp.Sdk.Extensibility.Project.Execute()
   PostSharp.Compiler.Hosting.PostSharpObject.InvokeProject(ProjectInvocation projectInvocation)

That is the whole stack as captured: the crash is at the top of MulticastAttributeTask, and there is no inner
exception.

Where to look

ProcessInheritedAttributesAcrossAssemblies walks a type's base type in a referenced assembly and asks, of each
custom attribute found there, whether it is inherited. The two-argument IsAttributeInherited overload is where it
fails, so the plausible candidates are the things that overload has to resolve and that can be absent when the
attribute comes from another assembly:

  • the attribute's own type, if it cannot be resolved from the referenced assembly's metadata,
  • the MulticastAttributeUsage / AttributeUsage declaration it looks for on that type, when the attribute is not
    a multicast attribute at all,
  • the AllowMultiple / inheritance property the requiresInheritanceProperty parameter selects, when the
    attribute type declares no such property.

Any of those would explain a crash that depends on what is in the referencing project's dependencies rather than
on the project being built, which is consistent with how rarely it is reported.

The user-visible effect is that the build fails with an unhandled exception rather than a PostSharp diagnostic, so
whatever the resolution, this path wants a null check and an error message naming the attribute and the base type.

Scale, and it is small

1 distinct installation, 1 report, 1 crash signature, over the retained window (three months). This is
reported honestly rather than argued up: on volume alone this defect would not be worth a maintainer's afternoon.

What makes it worth recording is that it is an unguarded null dereference in the SDK's own inheritance handling,
on a code path that a project reaches through its dependencies, so the single report is not evidence that a
single user is affected: any solution with the same reference shape would hit it, and the crash aborts the build
completely.

Version history:

Lineage Version Seen
2026.0 2026.0.9 2026-06-16
2025.0 2025.0.10 2026-01-08

Two lineages six months apart, so it is not a regression in 2026.0 and not new. 2026.0.9 is a current,
non-retired build (published 2026-05-15, replaced by 2026.0.10 on 2026-06-02), so this is not a defect that has
aged out; the report simply arrived once.

Reproduction

None available. No user description was attached, and the crash report carries no project, assembly or type names,
so the reference shape that triggers it cannot be recovered from the telemetry. A null check with a diagnostic may
be a better use of time than reproducing it.


Filed from CEIP crash reports. Invariant problem 26338; its id is recorded against this candidate in the triage
database. Figures cover the retained window (three months) and count distinct reporting installations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions