Summary
WatermarkTask.Execute enumerates the user licenses and dereferences each entry without testing it for null. When one entry is null, the whole compilation dies with an unhandled NullReferenceException reported as PS0099.
Symptom
error PS0099: Unhandled exception (postsharp-x64-srv.exe 2024.0.24 debug | .NET Framework 4.8.1 (X64)):
System.NullReferenceException: Object reference not set to an instance of an object.
error PS0099: at PostSharp.Sdk.Extensibility.Tasks.WatermarkTask.<>c.<Execute>b__0_1(LicenseConfiguration l)
error PS0099: at System.Linq.Enumerable.All[TSource](IEnumerable`1 source, Func`2 predicate)
error PS0099: at PostSharp.Sdk.Extensibility.Tasks.WatermarkTask.Execute()
error PS0099: at PostSharp.Sdk.Extensibility.Project.ExecutePhase(TaskPhase phase)
error PS0099: at PostSharp.Sdk.Extensibility.Project.Execute()
error PS0099: at PostSharp.Compiler.Hosting.PostSharpObject.InvokeProject(ProjectInvocation projectInvocation)
Diagnosis
if ( LocalUserLicenseManager.Instance.UserLicenses.All( l => l.License != null && l.License.RequiresWatermark() ) )
The lambda guards l.License, so the exception can only come from l itself being null: LocalUserLicenseManager.Instance.UserLicenses contained a null element.
What produces the null element has not been established. Worth noting that the affected process is postsharp-x64-srv.exe, the persistent pipe server, which serves many compilations in sequence, so a collection being enumerated while it is populated is one candidate — but that is a hypothesis, not a finding.
Whatever the origin, the task should not turn it into an unhandled exception. RequiresWatermark decides whether the assembly is watermarked as built with an evaluation licence, so a null entry should be treated as "does not require a watermark" and skipped, exactly like an entry whose License is null.
Frequency
Observed once, in a CI run of PostSharp 2024.0 / Test .NET Framework: Build Tests (Core), on the test Aspects.StateMachine.Iterator_OnException_OptimizeOff. That job runs WatermarkTask for each of its 371 tests, and only that one failed; the OptimizeOn variant of the same test passed seconds later, which is consistent with the null being transient rather than determined by the code under test.
Over the last 60 recorded runs of that test, it failed twice. The other failure, on an unrelated branch of the 2026.0 line, was a different licensing error (PS0242: No valid license key has been installed) and shows no WatermarkTask exception, so the two are not the same defect. What they have in common is that this test is sensitive to the licensing state of the agent.
Affected source
Core/PostSharp.Compiler.Engine/Sdk/Extensibility/Tasks/WatermarkTask.cs — Execute
Proposed fix
Drop the whole WatermarkTask as obsolete.
Environment
- PostSharp 2024.0.24, debug build,
postsharp-x64-srv.exe, .NET Framework 4.8.1 (X64)
-- Claude for Gael Fraiteur
Summary
WatermarkTask.Executeenumerates the user licenses and dereferences each entry without testing it for null. When one entry is null, the whole compilation dies with an unhandledNullReferenceExceptionreported asPS0099.Symptom
Diagnosis
The lambda guards
l.License, so the exception can only come fromlitself being null:LocalUserLicenseManager.Instance.UserLicensescontained a null element.What produces the null element has not been established. Worth noting that the affected process is
postsharp-x64-srv.exe, the persistent pipe server, which serves many compilations in sequence, so a collection being enumerated while it is populated is one candidate — but that is a hypothesis, not a finding.Whatever the origin, the task should not turn it into an unhandled exception.
RequiresWatermarkdecides whether the assembly is watermarked as built with an evaluation licence, so a null entry should be treated as "does not require a watermark" and skipped, exactly like an entry whoseLicenseis null.Frequency
Observed once, in a CI run of
PostSharp 2024.0 / Test .NET Framework: Build Tests (Core), on the testAspects.StateMachine.Iterator_OnException_OptimizeOff. That job runsWatermarkTaskfor each of its 371 tests, and only that one failed; theOptimizeOnvariant of the same test passed seconds later, which is consistent with the null being transient rather than determined by the code under test.Over the last 60 recorded runs of that test, it failed twice. The other failure, on an unrelated branch of the 2026.0 line, was a different licensing error (
PS0242: No valid license key has been installed) and shows noWatermarkTaskexception, so the two are not the same defect. What they have in common is that this test is sensitive to the licensing state of the agent.Affected source
Core/PostSharp.Compiler.Engine/Sdk/Extensibility/Tasks/WatermarkTask.cs—ExecuteProposed fix
Drop the whole WatermarkTask as obsolete.
Environment
postsharp-x64-srv.exe, .NET Framework 4.8.1 (X64)-- Claude for Gael Fraiteur