Codes in the SC0xx range are emitted by the verifier in consumer projects. Pairs are interleaved by mode: odd-numbered codes fire when the consumer is not using Central Package Management (metadata lives on <PackageReference> in the consumer csproj); even-numbered codes fire when the consumer is using CPM (metadata lives on <PackageVersion> in Directory.Packages.props). Sibling = code ± 1 — SC001/SC002, SC003/SC004, SC011/SC012, and so on. The trailing SC017–SC020 codes are unpaired (audit message, install-integrity check, and the two placement errors). Codes added from SC029 onward drop the interleaving and run as consecutive triples instead — non-CPM, CPM, owner mode — so SC029/SC030/SC031, SC032/SC033/SC034, SC035/SC036/SC037, and each triple through SC058 cover one scenario across all three placements. SC059 is unpaired for the same reason as SC017: it is an audit message that reads the same whatever the placement.
Owner mode (SC021–SC028). When the OSS author opts a package into owner mode (SponsorOwner="<id>" at pack time), the consumer configures sponsorship once, via global MSBuild properties (in Directory.Build.props or the consuming project), rather than per-package metadata. Because there is a single property source — no <PackageReference>/<PackageVersion> split — each scenario needs only one code, so SC021–SC028 are unpaired owner-mode counterparts of the per-package family: SC021↔SC001/SC002 (no config), SC022↔SC003/SC004 (conflicting modes), SC023↔SC005/SC006 (ignored), SC024↔SC007/SC008 (invalid account), SC025↔SC009/SC010 (expired), SC026↔SC011/SC012 (bad license date), SC027↔SC013/SC014 (bad SponsorshipStart), SC028↔SC015/SC016 (future SponsorshipStart). The placement-agnostic SC017 (attestation), SC018 (missing hash file) and SC059 (private-sponsorship attestation) are reused as-is; SC019/SC020 do not apply (no items to misplace).
Each paired scenario shares one author-side override metadatum: NoLicenseSpecifiedSeverityOverride applies to SC001, SC002, and the owner-mode SC021, and similarly for the rest. The split exists so each code can be documented, linked, and triaged independently — the underlying scenario is the same.
Every emitted message is prefixed with the code's short Name (e.g. No license specified. Package 'MyOssLib'...) and suffixed with See: https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#<code>. The Syntax/Example entries below show the inner format string only — the name and link wrap is added at log time.
The default severities below can be overridden by the OSS author at pack time, and the message body can be replaced with custom text, via paired metadata on <PackageReference Include="SponsorCheck">: <Stem>SeverityOverride and <Stem>MessageOverride for each of NoLicenseSpecified (SC001/SC002/SC021), LicenseIgnored (SC005/SC006/SC023), InvalidAccount (SC007/SC008/SC024), LicenseExpired (SC009/SC010/SC025). A single override value applies across the per-package, CPM, and owner-mode siblings. Other codes are consumer-side configuration bugs that the consumer must fix and so cannot be tuned. Severity values: error, warning, message. Message values: any string (the code's short Name and the docs link wrap still apply).
flowchart TD
Start([Consumer build]) --> Which{Which mode?}
Which -->|Ignored| SC005[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc005'>SC005 Warning<br/>In breach of license</a>]
Which -->|Publisher-defined exemption| KnownName{Name matches<br/>a publisher<br/>exemption?}
KnownName -->|No| SC032[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc032'>SC032 Error<br/>Unknown exemption name</a>]
KnownName -->|Yes| HasUntil{Exemption<br/>Until set?}
HasUntil -->|No| Capped{Publisher set<br/>MaxTermMonths?}
Capped -->|Yes| SC038[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc038'>SC038 Error<br/>End date required</a>]
Capped -->|No| SC029
HasUntil -->|Yes| UntilYM{Valid<br/>yyyy-MM?}
UntilYM -->|No| SC041[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc041'>SC041 Error<br/>Invalid date format</a>]
UntilYM -->|Yes| UntilCap{Beyond<br/>MaxTermMonths?}
UntilCap -->|Yes| SC044[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc044'>SC044 Error<br/>Beyond the publisher's cap</a>]
UntilCap -->|No| UntilExpired{End of month<br/>in the past?}
UntilExpired -->|Yes| SC047[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc047'>SC047 Error<br/>Exemption expired</a>]
UntilExpired -->|No| SC029
SC029[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc029'>SC029 Warning<br/>Publisher's criteria text</a>]
Which -->|Supplied sponsor account| HasPrivate{Sponsorship<br/>PrivateUntil set?}
HasPrivate -->|Yes| PrivateYM{Valid<br/>yyyy-MM?}
PrivateYM -->|No| SC050[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc050'>SC050 Error<br/>Invalid date format</a>]
PrivateYM -->|Yes| PrivateCap{Beyond the<br/>publisher's cap?}
PrivateCap -->|Yes| SC053[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc053'>SC053 Error<br/>Beyond the publisher's cap</a>]
PrivateCap -->|No| PrivateExpired{End of month<br/>in the past?}
PrivateExpired -->|Yes| SC056[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc056'>SC056 Error<br/>Private declaration expired</a>]
PrivateExpired -->|No| PassPrivate([<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc059'>Build passes<br/>SC059 audit message</a>])
HasPrivate -->|No| HasStart{Sponsorship<br/>Start set?}
HasStart -->|Yes| Future{Start in<br/>future?}
Future -->|Yes| SC015[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc015'>SC015 Error<br/>Date in future</a>]
Future -->|No| AfterPack{Start ><br/>PackDate?}
AfterPack -->|Yes| PassAttest([<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc017'>Build passes<br/>SC017 audit message</a>])
AfterPack -->|No| Match
HasStart -->|No| Match
Match{Supplied account<br/>exists in hash list?}
Match -->|Yes| PassSponsor([Build passes])
Match -->|No| SC007[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc007'>SC007 Error<br/>Account is not licensed for usage</a>]
Which -->|Licensed Until| ParseYM{Valid<br/>yyyy-MM?}
ParseYM -->|No| SC011[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc011'>SC011 Error<br/>Invalid date format</a>]
ParseYM -->|Yes| TooFar{More than<br/>1 year out?}
TooFar -->|Yes| SC035[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc035'>SC035 Error<br/>Beyond the 1 year cap</a>]
TooFar -->|No| Expired{End of month<br/>in the past?}
Expired -->|Yes| SC009[<a href='https://github.com/SimonCropp/SponsorCheck/blob/main/docs/VerifierDiagnosticCodes.md#sc009'>SC009 Error<br/>License expired</a>]
Expired -->|No| PassLicense([Build passes])
The decision logic above is identical across all three placements; only the emitted code differs. Terminal codes shown are the non-CPM (
<PackageReference>) variants. A CPM consumer (<PackageVersion>inDirectory.Packages.props) emits the+1sibling of each (SC005→SC006, SC007→SC008, SC029→SC030, SC032→SC033, SC035→SC036, …). An owner-mode consumer (sponsorship set via a global MSBuild property) emits the SC021–SC028 equivalent for the original modes (Ignored→SC023, no match→SC024, expired→SC025, invalid date→SC026, future start→SC028) plus the third code of each SC029-onward triple for the exemption and private-sponsorship branches (SC031, SC034, SC040, SC043, SC046, SC049, SC052, SC055, SC058) and SC037 for the one-year cap; SC017 and SC059 are shared. The exemption branch only fires when the publisher defined<SponsorExemption>items at pack time — packages without any exemptions never reachKnownName. TheMaxTermMonthssub-branch only fires for exemptions the publisher time-bounded; an uncapped one goes straight fromKnownNametoSC029, unless the consumer bound it themselves, in which caseUntilExpiredstill applies. The private-sponsorship branch is checked ahead ofSponsorshipStartbecause a valid declaration decides the build outright — a private or incognito sponsorship is never in the hash list regardless of when it began.
-
Name: No license specified
-
Level: Error
-
Meaning: No license mode set on the
<PackageReference>for ThePackage. CPM equivalent: SC002. -
Syntax:
Package '{PackageId}' requires license metadata on the <PackageReference> for '{PackageId}'. Add ONE of the following attributes to the existing <PackageReference> for '{PackageId}' in: {csprojPath} Option — Sponsor on {PlatformName} ({sponsorUrl}): <PackageReference Include="{PackageId}" Version="{version}" {PlatformMetadataName}="<your-{platform}-account>" /> Option — Time-bounded license (replace yyyy-MM with the last covered month): <PackageReference Include="{PackageId}" Version="{version}" SponsorshipLicensedUntil="yyyy-MM" /> Option — Mark as ignored (you accept that the build is in breach of the package license): <PackageReference Include="{PackageId}" Version="{version}" SponsorshipLicenseIgnored="true" /> Sponsor at: {sponsorUrls}One "Sponsor on..." option is rendered per platform the author has enabled. SponsorshipLicenseIgnored is listed last so the breach-of-license escape hatch sits after the legitimate options. When only one platform is configured the "Sponsor at:" block collapses to a single inline line:
Sponsor at {sponsorUrl}. -
Example:
Package 'MyOssLib' requires license metadata on the <PackageReference> for 'MyOssLib'. Add ONE of the following attributes to the existing <PackageReference> for 'MyOssLib' in: /work/MyApp/MyApp.csproj Option — Sponsor on GitHub Sponsors (https://github.com/sponsors/acmecorp): <PackageReference Include="MyOssLib" Version="1.2.3" GitHubSponsorAccount="<your-github-account>" /> Option — Time-bounded license (replace yyyy-MM with the last covered month): <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipLicensedUntil="yyyy-MM" /> Option — Mark as ignored (you accept that the build is in breach of the package license): <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipLicenseIgnored="true" /> Sponsor at https://github.com/sponsors/acmecorp
- Name: No license specified
- Level: Error
- Meaning: CPM sibling of SC001: no license mode set on the
<PackageVersion>for ThePackage inDirectory.Packages.props. Body shape matches SC001 with<PackageVersion>in place of<PackageReference>and the props file path in place of the csproj path. - Example opener:
Package 'MyOssLib' requires license metadata on the <PackageVersion> for 'MyOssLib' in Directory.Packages.props.
-
Name: Conflicting license modes
-
Level: Error
-
Meaning: Multiple license modes set on the same
<PackageReference>(mutually exclusive). CPM equivalent: SC004. -
Syntax:
Package '{PackageId}': mutually exclusive license modes are set on the <PackageReference> ({modes}). Pick one. Edit the <PackageReference> for '{PackageId}' in: {csprojPath} Keep exactly one of: GitHubSponsorAccount, OpenCollectiveSponsorAccount, PolarSponsorAccount, SponsorshipLicensedUntil, or SponsorshipLicenseIgnored. -
Example:
Package 'MyOssLib': mutually exclusive license modes are set on the <PackageReference> (Sponsor, SponsorshipLicenseIgnored). Pick one. Edit the <PackageReference> for 'MyOssLib' in: /work/MyApp/MyApp.csproj Keep exactly one of: GitHubSponsorAccount, OpenCollectiveSponsorAccount, PolarSponsorAccount, SponsorshipLicensedUntil, or SponsorshipLicenseIgnored.
- Name: Conflicting license modes
- Level: Error
- Meaning: CPM sibling of SC003: mutually exclusive license modes set on the same
<PackageVersion>inDirectory.Packages.props. - Example opener:
Package 'MyOssLib': mutually exclusive license modes are set on the <PackageVersion> in Directory.Packages.props (Sponsor, SponsorshipLicenseIgnored). Pick one.
-
Name: License ignored
-
Level: Warning
-
Meaning:
SponsorshipLicenseIgnored="true"on the<PackageReference>— consumer has opted out. CPM equivalent: SC006. -
Syntax:
Package '{PackageId}': SponsorshipLicenseIgnored="true" on the <PackageReference>. Build is allowed but is in breach of the package license. <SC001-style remediation block — see SC001 for the full format, minus the "Mark as ignored" option> -
Example: Same body shape as SC001 (but without the "Mark as ignored" option, since that mode is what already triggered this warning), prefixed with
Package 'MyOssLib': SponsorshipLicenseIgnored="true" on the <PackageReference>. Build is allowed but is in breach of the package license.
- Name: License ignored
- Level: Warning
- Meaning: CPM sibling of SC005:
SponsorshipLicenseIgnored="true"on the<PackageVersion>inDirectory.Packages.props. - Example opener:
Package 'MyOssLib': SponsorshipLicenseIgnored="true" on the <PackageVersion> in Directory.Packages.props. Build is allowed but is in breach of the package license.
-
Name: Invalid account
-
Level: Error
-
Meaning: None of the sponsor accounts declared on the
<PackageReference>match the bundled hash list. CPM equivalent: SC008. -
Syntax:
Package '{PackageId}': no sponsor account declared on the <PackageReference> matches the bundled list. Tried: {attempts} Sponsor at: {sponsorUrl1} {sponsorUrl2} ... If sponsorship started after this package was released, attest to the start date in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" {PlatformMetadataName}="{accountValue}" SponsorshipStart="yyyy-MM-dd" />The "Sponsor at:" block is omitted when the author did not bundle any platform accounts. When only one platform is configured it collapses to a single inline line:
Sponsor at {sponsorUrl}. The "If sponsorship started after this package was released..." block is omitted whenSponsorshipStartis already set on the consumer side. -
Example:
Package 'MyOssLib': no sponsor account declared on the <PackageReference> matches the bundled list. Tried: GitHubSponsors=mallory Sponsor at: https://github.com/sponsors/acmecorp https://opencollective.com/acme-org https://polar.sh/acme If sponsorship started after this package was released, attest to the start date in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="MyOssLib" Version="1.2.3" GitHubSponsorAccount="mallory" SponsorshipStart="yyyy-MM-dd" />
- Name: Invalid account
- Level: Error
- Meaning: CPM sibling of SC007: no sponsor account declared on the
<PackageVersion>inDirectory.Packages.propsmatches the bundled hash list. - Example opener:
Package 'MyOssLib': no sponsor account declared on the <PackageVersion> in Directory.Packages.props matches the bundled list.
-
Name: License expired
-
Level: Error
-
Meaning:
SponsorshipLicensedUntilon the<PackageReference>has expired. CPM equivalent: SC010. -
Syntax:
Package '{PackageId}': SponsorshipLicensedUntil='{value}' on the <PackageReference> has expired (end of month {endOfMonth:yyyy-MM-dd} UTC). Renew the license in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipLicensedUntil="yyyy-MM" /> Sponsor at {sponsorUrl} ← single-platform inline formOr as an alternative to renewal, the consumer can switch to sponsorship — the "Sponsor at" block lists the author's configured sponsor URLs (inline for one platform, indented
Sponsor at:\n url1\n url2block for multiple). -
Example:
Package 'MyOssLib': SponsorshipLicensedUntil='2000-01' on the <PackageReference> has expired (end of month 2000-01-31 UTC). Renew the license in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipLicensedUntil="yyyy-MM" /> Sponsor at https://github.com/sponsors/acmecorp
- Name: License expired
- Level: Error
- Meaning: CPM sibling of SC009:
SponsorshipLicensedUntilon the<PackageVersion>inDirectory.Packages.propshas expired. - Example opener:
Package 'MyOssLib': SponsorshipLicensedUntil='2000-01' on the <PackageVersion> in Directory.Packages.props has expired (end of month 2000-01-31 UTC).
- Name: Metadata set on both PackageReference and PackageVersion
- Level: Error
- Meaning: Defensive backstop: metadata set on both PackageReference and PackageVersion. SC020 normally fires first now (because the wrong-side metadatum is itself a placement violation) — SC019 only surfaces if SC020's check is bypassed.
- Syntax:
{metadataName}: set on both PackageReference ('{r}') and PackageVersion ('{v}'). Set on only one. - Example:
GitHubSponsorAccount: set on both PackageReference ('alice') and PackageVersion ('bob'). Set on only one.
-
Name: Invalid license date format
-
Level: Error
-
Meaning:
SponsorshipLicensedUntilon a<PackageReference>is not inyyyy-MMformat. The CPM equivalent is SC012. -
Syntax:
Package '{PackageId}': SponsorshipLicensedUntil='{value}' on the <PackageReference> is not in 'yyyy-MM' format. Fix the SponsorshipLicensedUntil attribute in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipLicensedUntil="yyyy-MM" /> -
Example:
Package 'MyOssLib': SponsorshipLicensedUntil='not-a-date' on the <PackageReference> is not in 'yyyy-MM' format. Fix the SponsorshipLicensedUntil attribute in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipLicensedUntil="yyyy-MM" />
-
Name: Invalid license date format
-
Level: Error
-
Meaning:
SponsorshipLicensedUntilon a<PackageVersion>(Central Package Management) is not inyyyy-MMformat. The non-CPM equivalent is SC011. -
Syntax:
Package '{PackageId}': SponsorshipLicensedUntil='{value}' on the <PackageVersion> in Directory.Packages.props is not in 'yyyy-MM' format. Fix the SponsorshipLicensedUntil attribute in: {directoryPackagesPropsPath} Example format: <PackageVersion Include="{PackageId}" Version="{version}" SponsorshipLicensedUntil="yyyy-MM" /> -
Example:
Package 'MyOssLib': SponsorshipLicensedUntil='not-a-date' on the <PackageVersion> in Directory.Packages.props is not in 'yyyy-MM' format. Fix the SponsorshipLicensedUntil attribute in: /work/MyApp/Directory.Packages.props Example format: <PackageVersion Include="MyOssLib" Version="1.2.3" SponsorshipLicensedUntil="yyyy-MM" />
- Name: Sponsorship attestation trusted
- Level: Info
- Meaning:
SponsorshipStartis after pack date — verifier trusts the attestation (audit trail message). - Syntax:
Package '{PackageId}': trusting unverified sponsor declaration ({attempts}): SponsorshipStart={startDate:yyyy-MM-dd} is later than package release {packDate:yyyy-MM-dd}, so the bundled sponsor list cannot contain this account. - Example:
Package 'MyOssLib': trusting unverified sponsor declaration (GitHubSponsors=carol): SponsorshipStart=2026-04-30 is later than package release 2026-04-15, so the bundled sponsor list cannot contain this account.
- Name: Bundled sponsor hash file missing
- Level: Error
- Meaning: Bundled sponsor hash file is missing from the package (corrupt install).
- Syntax:
Package '{PackageId}': bundled sponsor hash file not found at '{path}'. - Example:
Package 'MyOssLib': bundled sponsor hash file not found at 'C:\Users\me\.nuget\packages\myosslib\1.0.0\build\SponsorCheck.SponsorHashes.txt'.
-
Name: Invalid SponsorshipStart format
-
Level: Error
-
Meaning:
SponsorshipStarton the<PackageReference>is not inyyyy-MM-ddformat. CPM equivalent: SC014. -
Syntax:
Package '{PackageId}': SponsorshipStart='{value}' on the <PackageReference> is not in 'yyyy-MM-dd' format. Fix the SponsorshipStart attribute in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipStart="yyyy-MM-dd" /> -
Example:
Package 'MyOssLib': SponsorshipStart='yesterday' on the <PackageReference> is not in 'yyyy-MM-dd' format. Fix the SponsorshipStart attribute in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipStart="yyyy-MM-dd" />
- Name: Invalid SponsorshipStart format
- Level: Error
- Meaning: CPM sibling of SC013:
SponsorshipStarton the<PackageVersion>inDirectory.Packages.propsis not inyyyy-MM-ddformat. - Example opener:
Package 'MyOssLib': SponsorshipStart='yesterday' on the <PackageVersion> in Directory.Packages.props is not in 'yyyy-MM-dd' format.
-
Name: SponsorshipStart in the future
-
Level: Error
-
Meaning:
SponsorshipStarton the<PackageReference>is in the future. CPM equivalent: SC016. -
Syntax:
Package '{PackageId}': SponsorshipStart='{value}' on the <PackageReference> is in the future. Fix the SponsorshipStart attribute in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipStart="yyyy-MM-dd" /> -
Example:
Package 'MyOssLib': SponsorshipStart='2099-01-01' on the <PackageReference> is in the future. Fix the SponsorshipStart attribute in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipStart="yyyy-MM-dd" />
- Name: SponsorshipStart in the future
- Level: Error
- Meaning: CPM sibling of SC015:
SponsorshipStarton the<PackageVersion>inDirectory.Packages.propsis in the future. - Example opener:
Package 'MyOssLib': SponsorshipStart='2099-01-01' on the <PackageVersion> in Directory.Packages.props is in the future.
-
Name: Sponsor metadata in the wrong location
-
Level: Error
-
Meaning: Under Central Package Management (
ManagePackageVersionsCentrally=true) the SponsorCheck metadata must live on<PackageVersion>inDirectory.Packages.props, not on<PackageReference>in the consumer's csproj. The mirror also holds: without CPM the metadata must live on<PackageReference>, not on<PackageVersion>. -
Syntax (multiple misplaced attributes):
Package '{PackageId}' uses Central Package Management, so SponsorCheck metadata must live on <PackageVersion> in Directory.Packages.props — not on <PackageReference>. Move the following attributes off the <PackageReference> for '{PackageId}' in: {csprojPath} - {misplacedMetadata1} - {misplacedMetadata2} ...and onto the <PackageVersion> for '{PackageId}' in: {directoryPackagesPropsPath}The first sentence inverts (
is not using/<PackageReference>↔<PackageVersion>↔Directory.Packages.props↔ csproj) when CPM is off. -
Syntax (single misplaced attribute):
Package '{PackageId}' uses Central Package Management, so SponsorCheck metadata must live on <PackageVersion> in Directory.Packages.props — not on <PackageReference>. Move the {misplacedMetadata} attribute from the <PackageReference> for '{PackageId}' to the <PackageVersion> for '{PackageId}' in: {directoryPackagesPropsPath} -
Example (single attribute):
Package 'MyOssLib' uses Central Package Management, so SponsorCheck metadata must live on <PackageVersion> in Directory.Packages.props — not on <PackageReference>. Move the SponsorshipLicenseIgnored attribute from the <PackageReference> for 'MyOssLib' to the <PackageVersion> for 'MyOssLib' in: /work/MyApp/Directory.Packages.props
-
Name: No license specified
-
Level: Error
-
Meaning: Owner-mode equivalent of SC001/SC002: the package is published in owner mode (
SponsorOwner), so sponsorship is configured via a global MSBuild property, but none was set. Author override metadatum:NoLicenseSpecifiedSeverityOverride/NoLicenseSpecifiedMessageOverride. -
Syntax:
Package '{PackageId}' requires a SponsorCheck license property. '{PackageId}' is published in owner mode, so sponsorship is configured once via an MSBuild property (in Directory.Build.props or the consuming project). Set ONE of the following properties (in a <PropertyGroup> in Directory.Build.props or the consuming project): Option — Sponsor on {PlatformName} ({sponsorUrl}): <{OwnerId}_{PlatformMetadataName}><your-{platform}-account></{OwnerId}_{PlatformMetadataName}> Option — Time-bounded license (replace yyyy-MM with the last covered month): <{OwnerId}_SponsorshipLicensedUntil>yyyy-MM</{OwnerId}_SponsorshipLicensedUntil> Option — Mark as ignored (you accept that the build is in breach of the package license): <{OwnerId}_SponsorshipLicenseIgnored>true</{OwnerId}_SponsorshipLicenseIgnored> Sponsor at: {sponsorUrls}One "Sponsor on..." option is rendered per platform the author has enabled. The property names are the per-package metadata names prefixed with the package's owner id (e.g.
<acme_GitHubSponsorAccount>whenSponsorOwner="acme") — this keeps two owner-mode packages from different authors independently configurable in the same consumer project. The "Sponsor at:" block collapses to a single inline line when only one platform is configured. -
Example:
Package 'MyOssLib' requires a SponsorCheck license property. 'MyOssLib' is published in owner mode, so sponsorship is configured once via an MSBuild property (in Directory.Build.props or the consuming project). Set ONE of the following properties (in a <PropertyGroup> in Directory.Build.props or the consuming project): Option — Sponsor on GitHub Sponsors (https://github.com/sponsors/acmecorp): <acme_GitHubSponsorAccount><your-github-account></acme_GitHubSponsorAccount> Option — Time-bounded license (replace yyyy-MM with the last covered month): <acme_SponsorshipLicensedUntil>yyyy-MM</acme_SponsorshipLicensedUntil> Option — Mark as ignored (you accept that the build is in breach of the package license): <acme_SponsorshipLicenseIgnored>true</acme_SponsorshipLicenseIgnored> Sponsor at https://github.com/sponsors/acmecorp
-
Name: Conflicting license modes
-
Level: Error
-
Meaning: Owner-mode equivalent of SC003/SC004: mutually exclusive license properties are set (e.g. both a sponsor account property and
SponsorshipLicenseIgnored). -
Syntax:
Package '{PackageId}': mutually exclusive license properties are set ({modes}). Pick one. Edit the SponsorCheck properties for '{PackageId}' in Directory.Build.props or the consuming project. Keep exactly one of: {OwnerId}_GitHubSponsorAccount, {OwnerId}_OpenCollectiveSponsorAccount, {OwnerId}_PolarSponsorAccount, {OwnerId}_SponsorshipLicensedUntil, or {OwnerId}_SponsorshipLicenseIgnored. -
Example opener:
Package 'MyOssLib': mutually exclusive license properties are set (Sponsor, SponsorshipLicenseIgnored). Pick one.
-
Name: License ignored
-
Level: Warning
-
Meaning: Owner-mode equivalent of SC005/SC006: the
SponsorshipLicenseIgnored=trueproperty is set — the consumer has opted out. Author override metadatum:LicenseIgnoredSeverityOverride/LicenseIgnoredMessageOverride. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipLicenseIgnored="true" property is set. Build is allowed but is in breach of the package license. <SC021-style remediation block — see SC021 for the full format, minus the "Mark as ignored" option> -
Example opener:
Package 'MyOssLib': acme_SponsorshipLicenseIgnored="true" property is set. Build is allowed but is in breach of the package license.
-
Name: Invalid account
-
Level: Error
-
Meaning: Owner-mode equivalent of SC007/SC008: no sponsor account property matches the bundled hash list. Author override metadatum:
InvalidAccountSeverityOverride/InvalidAccountMessageOverride. -
Syntax:
Package '{PackageId}': no sponsor account property matches the bundled list. Tried: {attempts} Sponsor at: {sponsorUrl1} {sponsorUrl2} If sponsorship started after this package was released, attest to the start date by setting the {OwnerId}_SponsorshipStart property in Directory.Build.props or the consuming project. Example format: <{OwnerId}_{PlatformMetadataName}>{accountValue}</{OwnerId}_{PlatformMetadataName}> <{OwnerId}_SponsorshipStart>yyyy-MM-dd</{OwnerId}_SponsorshipStart>The "If sponsorship started after this package was released..." block is omitted when
{OwnerId}_SponsorshipStartis already set. -
Example:
Package 'MyOssLib': no sponsor account property matches the bundled list. Tried: GitHubSponsors=mallory Sponsor at https://github.com/sponsors/acmecorp If sponsorship started after this package was released, attest to the start date by setting the acme_SponsorshipStart property in Directory.Build.props or the consuming project. Example format: <acme_GitHubSponsorAccount>mallory</acme_GitHubSponsorAccount> <acme_SponsorshipStart>yyyy-MM-dd</acme_SponsorshipStart>
-
Name: License expired
-
Level: Error
-
Meaning: Owner-mode equivalent of SC009/SC010: the
SponsorshipLicensedUntilproperty has expired. Author override metadatum:LicenseExpiredSeverityOverride/LicenseExpiredMessageOverride. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipLicensedUntil='{value}' property has expired (end of month {endOfMonth:yyyy-MM-dd} UTC). Renew the license by updating the {OwnerId}_SponsorshipLicensedUntil property in Directory.Build.props or the consuming project. Example format: <{OwnerId}_SponsorshipLicensedUntil>yyyy-MM</{OwnerId}_SponsorshipLicensedUntil> Sponsor at {sponsorUrl} -
Example opener:
Package 'MyOssLib': acme_SponsorshipLicensedUntil='2000-01' property has expired (end of month 2000-01-31 UTC).
-
Name: Invalid license date format
-
Level: Error
-
Meaning: Owner-mode equivalent of SC011/SC012: the
SponsorshipLicensedUntilproperty is not inyyyy-MMformat. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipLicensedUntil='{value}' property is not in 'yyyy-MM' format. Fix the {OwnerId}_SponsorshipLicensedUntil property in Directory.Build.props or the consuming project. Example format: <{OwnerId}_SponsorshipLicensedUntil>yyyy-MM</{OwnerId}_SponsorshipLicensedUntil> -
Example opener:
Package 'MyOssLib': acme_SponsorshipLicensedUntil='not-a-date' property is not in 'yyyy-MM' format.
-
Name: Invalid SponsorshipStart format
-
Level: Error
-
Meaning: Owner-mode equivalent of SC013/SC014: the
SponsorshipStartproperty is not inyyyy-MM-ddformat. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipStart='{value}' property is not in 'yyyy-MM-dd' format. Fix the {OwnerId}_SponsorshipStart property in Directory.Build.props or the consuming project. Example format: <{OwnerId}_SponsorshipStart>yyyy-MM-dd</{OwnerId}_SponsorshipStart> -
Example opener:
Package 'MyOssLib': acme_SponsorshipStart='yesterday' property is not in 'yyyy-MM-dd' format.
-
Name: SponsorshipStart in the future
-
Level: Error
-
Meaning: Owner-mode equivalent of SC015/SC016: the
SponsorshipStartproperty is in the future. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipStart='{value}' property is in the future. Fix the {OwnerId}_SponsorshipStart property in Directory.Build.props or the consuming project. Example format: <{OwnerId}_SponsorshipStart>yyyy-MM-dd</{OwnerId}_SponsorshipStart> -
Example opener:
Package 'MyOssLib': acme_SponsorshipStart='2099-01-01' property is in the future.
- Name: Exemption claimed
- Level: Warning
- Meaning: The consumer set
SponsorshipExemption="<name>"on the<PackageReference>and<name>matches an exemption the publisher defined at pack time. The build passes; the warning body includes the publisher's verbatim exemption criteria so the audit trail in CI logs documents the exact carve-out being claimed (not a generic "in breach" message). The matched name appears with the consumer-typed casing — lookup is case-insensitive but what the consumer wrote is what's surfaced. Not overrideable: the publisher'sMessageis the override. CPM equivalent: SC030. Owner-mode equivalent: SC031. - Syntax:
Package '{PackageId}': SponsorshipExemption="{name}" claimed on the <PackageReference>. Publisher's exemption criteria: {publisherMessage} - Example:
Package 'Papyrine': SponsorshipExemption="Consulting" claimed on the <PackageReference>. Publisher's exemption criteria: Organizations that have engaged any of the core maintainers in consulting work could be exempt from the Maintenance Fee for 6 months from the final date of that work.
- Name: Exemption claimed
- Level: Warning
- Meaning: CPM equivalent of SC029: the consumer set
SponsorshipExemptionon the<PackageVersion>inDirectory.Packages.propsand the name matches a publisher-defined exemption. - Syntax:
Package '{PackageId}': SponsorshipExemption="{name}" claimed on the <PackageVersion> in Directory.Packages.props. Publisher's exemption criteria: {publisherMessage} - Example:
Package 'Papyrine': SponsorshipExemption="SmallRevenue" claimed on the <PackageVersion> in Directory.Packages.props. Publisher's exemption criteria: Consumers under US$10,000 annual gross revenue are exempt.
- Name: Exemption claimed
- Level: Warning
- Meaning: Owner-mode equivalent of SC029/SC030: the owner-prefixed
{OwnerId}_SponsorshipExemptionglobal property is set and names a publisher-defined exemption. - Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipExemption="{name}" property is set. Publisher's exemption criteria: {publisherMessage} - Example:
Package 'Papyrine': papyrine_SponsorshipExemption="Consulting" property is set. Publisher's exemption criteria: Organizations that have engaged any of the core maintainers in consulting work could be exempt from the Maintenance Fee for 6 months from the final date of that work.
-
Name: Unknown exemption
-
Level: Error
-
Meaning: The consumer set
SponsorshipExemption="<name>"on the<PackageReference>but<name>does not match any exemption the publisher defined at pack time. The body lists the publisher-defined exemptions with their criteria text so the consumer can choose, or reports that the publisher has not defined any exemptions (in which case the consumer needs to pick a different license mode — see SC001). Lookup is case-insensitive — a typo or a removed exemption name is the typical cause. Not overrideable. CPM equivalent: SC033. Owner-mode equivalent: SC034. -
Syntax:
Package '{PackageId}': SponsorshipExemption="{name}" on the <PackageReference> does not name a known exemption. Available exemptions: - {name1}: {message1} - {name2}: {message2} Claim one in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipExemption="{name1}" />When the publisher has not defined any exemptions the "Available exemptions" block is replaced with
The publisher has not defined any exemptions for this package. -
Example:
Package 'Papyrine': SponsorshipExemption="MadeUpName" on the <PackageReference> does not name a known exemption. Available exemptions: - Consulting: Organizations that have engaged any of the core maintainers in consulting work could be exempt from the Maintenance Fee for 6 months from the final date of that work. - SmallRevenue: Consumers under US$10,000 annual gross revenue are exempt. Claim one in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="Papyrine" Version="1.0.0" SponsorshipExemption="Consulting" />
- Name: Unknown exemption
- Level: Error
- Meaning: CPM equivalent of SC032.
- Syntax: Same structure as SC032 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': SponsorshipExemption="MadeUpName" on the <PackageVersion> in Directory.Packages.props does not name a known exemption.
- Name: Unknown exemption
- Level: Error
- Meaning: Owner-mode equivalent of SC032/SC033: the
{OwnerId}_SponsorshipExemptionproperty names an exemption the publisher did not define. - Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipExemption="{name}" does not name a known exemption.(body uses the owner-mode "Claim one by setting the property" remediation block.) - Example opener:
Package 'Papyrine': papyrine_SponsorshipExemption="MadeUpName" does not name a known exemption.
-
Name: License too far in the future
-
Level: Error
-
Meaning:
SponsorshipLicensedUntilon the<PackageReference>is dated more than one year past the build clock. The value is an unverified consumer-side self-attestation, so it is capped: without a ceiling,SponsorshipLicensedUntil="9999-12"would be a permanent opt-out dressed up as a license. The cap is the same calendar month one year out, inclusive — with a build in 2026-05,2027-05is the last accepted value and2027-06fails. Not overrideable. CPM equivalent: SC036. Owner-mode equivalent: SC037. -
Syntax:
Package '{PackageId}': SponsorshipLicensedUntil='{value}' on the <PackageReference> is more than 1 year in the future (maximum {maxMonth}). Set the SponsorshipLicensedUntil attribute to {maxMonth} or earlier in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipLicensedUntil="{maxMonth}" />Unlike the SC011 format-fix block, the example renders the actual cap month rather than a literal
yyyy-MMplaceholder, so it is directly pasteable. -
Example:
Package 'MyOssLib': SponsorshipLicensedUntil='2030-01' on the <PackageReference> is more than 1 year in the future (maximum 2027-05). Set the SponsorshipLicensedUntil attribute to 2027-05 or earlier in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="MyOssLib" Version="1.2.3" SponsorshipLicensedUntil="2027-05" />
- Name: License too far in the future
- Level: Error
- Meaning: CPM equivalent of SC035:
SponsorshipLicensedUntilon the<PackageVersion>inDirectory.Packages.propsis dated more than one year out. Body shape matches SC035 with<PackageVersion>in place of<PackageReference>and the props file path in place of the csproj path. - Example opener:
Package 'MyOssLib': SponsorshipLicensedUntil='2030-01' on the <PackageVersion> in Directory.Packages.props is more than 1 year in the future (maximum 2027-05).
-
Name: License too far in the future
-
Level: Error
-
Meaning: Owner-mode equivalent of SC035/SC036: the
{OwnerId}_SponsorshipLicensedUntilproperty is dated more than one year out. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipLicensedUntil='{value}' property is more than 1 year in the future (maximum {maxMonth}). Set the {OwnerId}_SponsorshipLicensedUntil property to {maxMonth} or earlier in Directory.Build.props or the consuming project. Example format: <{OwnerId}_SponsorshipLicensedUntil>{maxMonth}</{OwnerId}_SponsorshipLicensedUntil> -
Example opener:
Package 'MyOssLib': acme_SponsorshipLicensedUntil='2030-01' property is more than 1 year in the future (maximum 2027-05).
-
Name: Exemption end date required
-
Level: Error
-
Meaning: The consumer claimed an exemption on the
<PackageReference>that the publisher time-bounds (MaxTermMonthswas set on the<SponsorExemption>at pack time), but did not supplySponsorshipExemptionUntil. A time-bounded exemption exists so a carve-out that stops applying — the consulting engagement ended, the revenue threshold was crossed — fails the build rather than riding along unnoticed, which is only possible if the claim carries an end month. Not overrideable. CPM equivalent: SC039. Owner-mode equivalent: SC040. -
Syntax:
Package '{PackageId}': SponsorshipExemption="{name}" on the <PackageReference> is missing SponsorshipExemptionUntil — the publisher time-bounds this exemption to {n} months. Set the SponsorshipExemptionUntil attribute to {maxMonth} or earlier in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipExemption="{name}" SponsorshipExemptionUntil="{maxMonth}" />{maxMonth}is the ceiling measured from the build clock, so it rolls forward with time — an already-declared month stays valid, but each renewal is capped afresh. -
Example:
Package 'Papyrine': SponsorshipExemption="Consulting" on the <PackageReference> is missing SponsorshipExemptionUntil — the publisher time-bounds this exemption to 6 months. Set the SponsorshipExemptionUntil attribute to 2026-11 or earlier in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="Papyrine" Version="1.0.0" SponsorshipExemption="Consulting" SponsorshipExemptionUntil="2026-11" />
- Name: Exemption end date required
- Level: Error
- Meaning: CPM equivalent of SC038: the claim lives on the
<PackageVersion>inDirectory.Packages.propsand is missingSponsorshipExemptionUntil. - Syntax:
Package '{PackageId}': SponsorshipExemption="{name}" on the <PackageVersion> in Directory.Packages.props is missing SponsorshipExemptionUntil — the publisher time-bounds this exemption to {n} months.(body shape matches SC038 with the props file path.) - Example opener:
Package 'Papyrine': SponsorshipExemption="Consulting" on the <PackageVersion> in Directory.Packages.props is missing SponsorshipExemptionUntil — the publisher time-bounds this exemption to 6 months.
-
Name: Exemption end date required
-
Level: Error
-
Meaning: Owner-mode equivalent of SC038/SC039: the
{OwnerId}_SponsorshipExemptionproperty names a time-bounded exemption but{OwnerId}_SponsorshipExemptionUntilis unset. -
Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipExemption="{name}" property is set, but the publisher time-bounds this exemption to {n} months, so {OwnerId}_SponsorshipExemptionUntil must be set too. Set the {OwnerId}_SponsorshipExemptionUntil property to {maxMonth} or earlier in Directory.Build.props or the consuming project. Example format: <{OwnerId}_SponsorshipExemption>{name}</{OwnerId}_SponsorshipExemption> <{OwnerId}_SponsorshipExemptionUntil>{maxMonth}</{OwnerId}_SponsorshipExemptionUntil> -
Example opener:
Package 'Papyrine': papyrine_SponsorshipExemption="Consulting" property is set, but the publisher time-bounds this exemption to 6 months, so papyrine_SponsorshipExemptionUntil must be set too.
-
Name: Invalid exemption end date format
-
Level: Error
-
Meaning:
SponsorshipExemptionUntilon the<PackageReference>is not ayyyy-MMmonth. The format matches SponsorshipLicensedUntil — month granularity, so a claim covers whole months and a build never breaks partway through one. Fires whether or not the publisher setMaxTermMonths: an unparseable value is a configuration bug either way. Not overrideable. CPM equivalent: SC042. Owner-mode equivalent: SC043. -
Syntax:
Package '{PackageId}': SponsorshipExemptionUntil='{value}' on the <PackageReference> is not in 'yyyy-MM' format. Fix the SponsorshipExemptionUntil attribute in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipExemption="{name}" SponsorshipExemptionUntil="yyyy-MM" /> -
Example opener:
Package 'Papyrine': SponsorshipExemptionUntil='2027-02-01' on the <PackageReference> is not in 'yyyy-MM' format.
- Name: Invalid exemption end date format
- Level: Error
- Meaning: CPM equivalent of SC041.
- Syntax: Same structure as SC041 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': SponsorshipExemptionUntil='2027-02-01' on the <PackageVersion> in Directory.Packages.props is not in 'yyyy-MM' format.
- Name: Invalid exemption end date format
- Level: Error
- Meaning: Owner-mode equivalent of SC041/SC042.
- Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipExemptionUntil='{value}' property is not in 'yyyy-MM' format.(body uses the owner-mode property remediation block.) - Example opener:
Package 'Papyrine': papyrine_SponsorshipExemptionUntil='later' property is not in 'yyyy-MM' format.
-
Name: Exemption end date too far in the future
-
Level: Error
-
Meaning:
SponsorshipExemptionUntilon the<PackageReference>is dated further out than the publisher'sMaxTermMonthsallows. Without the ceiling a consumer could satisfy SC038 with9999-12and turn the required end date into a formality. The ceiling is measured from the build clock and is inclusive: withMaxTermMonths="6"and a build in 2026-05,2026-11is the last accepted value and2026-12fails. Because it moves with the clock, an already-valid claim keeps passing until it expires — it is each renewal that is capped. Only fires for a capped exemption; an uncapped one has no ceiling to exceed. Not overrideable. CPM equivalent: SC045. Owner-mode equivalent: SC046. -
Syntax:
Package '{PackageId}': SponsorshipExemptionUntil='{value}' on the <PackageReference> is more than {n} months in the future (maximum {maxMonth}). Set the SponsorshipExemptionUntil attribute to {maxMonth} or earlier in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipExemption="{name}" SponsorshipExemptionUntil="{maxMonth}" /> -
Example:
Package 'Papyrine': SponsorshipExemptionUntil='2026-12' on the <PackageReference> is more than 6 months in the future (maximum 2026-11). Set the SponsorshipExemptionUntil attribute to 2026-11 or earlier in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="Papyrine" Version="1.0.0" SponsorshipExemption="Consulting" SponsorshipExemptionUntil="2026-11" />
- Name: Exemption end date too far in the future
- Level: Error
- Meaning: CPM equivalent of SC044.
- Syntax: Same structure as SC044 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': SponsorshipExemptionUntil='2026-12' on the <PackageVersion> in Directory.Packages.props is more than 6 months in the future (maximum 2026-11).
- Name: Exemption end date too far in the future
- Level: Error
- Meaning: Owner-mode equivalent of SC044/SC045.
- Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipExemptionUntil='{value}' property is more than {n} months in the future (maximum {maxMonth}).(body uses the owner-mode property remediation block.) - Example opener:
Package 'Papyrine': papyrine_SponsorshipExemptionUntil='2026-12' property is more than 6 months in the future (maximum 2026-11).
-
Name: Exemption expired
-
Level: Error
-
Meaning: The exemption claimed on the
<PackageReference>carried aSponsorshipExemptionUntilmonth that has now passed. This is the forcing function the whole mechanism exists for: the build fails until someone confirms the carve-out still applies and renews the date, or switches to another license mode. Expiry is decided at month granularity, matching SC009 — the named month is fully covered through its final instant, and the first day of the next month is the cutoff. Fires for a consumer-supplied end month whether or not the publisher required one, so a voluntary self-imposed bound is enforced too. Not overrideable. CPM equivalent: SC048. Owner-mode equivalent: SC049. -
Syntax:
Package '{PackageId}': SponsorshipExemption="{name}" on the <PackageReference> expired — SponsorshipExemptionUntil='{value}' (end of month {lastDay} UTC). Confirm the exemption still applies, then set the SponsorshipExemptionUntil attribute to {maxMonth} or earlier in: {csprojPath} Otherwise switch to another license mode. Example format: <PackageReference Include="{PackageId}" Version="{version}" SponsorshipExemption="{name}" SponsorshipExemptionUntil="{maxMonth}" />When the publisher did not set
MaxTermMonthsthere is no ceiling to name, so theto {maxMonth} or earlierclause is omitted and the example renders the literalyyyy-MMplaceholder. -
Example:
Package 'Papyrine': SponsorshipExemption="Consulting" on the <PackageReference> expired — SponsorshipExemptionUntil='2026-04' (end of month 2026-04-30 UTC). Confirm the exemption still applies, then set the SponsorshipExemptionUntil attribute to 2026-11 or earlier in: /work/MyApp/MyApp.csproj Otherwise switch to another license mode. Example format: <PackageReference Include="Papyrine" Version="1.0.0" SponsorshipExemption="Consulting" SponsorshipExemptionUntil="2026-11" />
- Name: Exemption expired
- Level: Error
- Meaning: CPM equivalent of SC047.
- Syntax: Same structure as SC047 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': SponsorshipExemption="Consulting" on the <PackageVersion> in Directory.Packages.props expired — SponsorshipExemptionUntil='2026-04' (end of month 2026-04-30 UTC).
- Name: Exemption expired
- Level: Error
- Meaning: Owner-mode equivalent of SC047/SC048.
- Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipExemption="{name}" expired — {OwnerId}_SponsorshipExemptionUntil='{value}' (end of month {lastDay} UTC).(body uses the owner-mode property remediation block.) - Example opener:
Package 'Papyrine': papyrine_SponsorshipExemption="Consulting" expired — papyrine_SponsorshipExemptionUntil='2026-04' (end of month 2026-04-30 UTC).
-
Name: Invalid private sponsorship end date format
-
Level: Error
-
Meaning:
SponsorshipPrivateUntilon the<PackageReference>is not ayyyy-MMmonth. The attribute declares that the sponsorship is private on GitHub Sponsors, or incognito on Open Collective, and therefore deliberately absent from the bundled hash list — see Private and incognito sponsors. Not overrideable: the value is a consumer-side configuration bug. CPM equivalent: SC051. Owner-mode equivalent: SC052. -
Syntax:
Package '{PackageId}': SponsorshipPrivateUntil='{value}' on the <PackageReference> is not in 'yyyy-MM' format. Fix the SponsorshipPrivateUntil attribute in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" {platformMetadata}="{account}" SponsorshipPrivateUntil="yyyy-MM" /> -
Example:
Package 'Papyrine': SponsorshipPrivateUntil='April 2027' on the <PackageReference> is not in 'yyyy-MM' format. Fix the SponsorshipPrivateUntil attribute in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="Papyrine" Version="1.0.0" GitHubSponsorAccount="octocat" SponsorshipPrivateUntil="yyyy-MM" />
- Name: Invalid private sponsorship end date format
- Level: Error
- Meaning: CPM equivalent of SC050.
- Syntax: Same structure as SC050 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': SponsorshipPrivateUntil='April 2027' on the <PackageVersion> in Directory.Packages.props is not in 'yyyy-MM' format.
- Name: Invalid private sponsorship end date format
- Level: Error
- Meaning: Owner-mode equivalent of SC050/SC051.
- Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipPrivateUntil='{value}' property is not in 'yyyy-MM' format.(body uses the owner-mode property remediation block.) - Example opener:
Package 'Papyrine': papyrine_SponsorshipPrivateUntil='April 2027' property is not in 'yyyy-MM' format.
-
Name: Private sponsorship end date too far in the future
-
Level: Error
-
Meaning:
SponsorshipPrivateUntilnames a month beyond the publisher's cap, measured from the build clock. The cap defaults to 12 months and the author sets it withPrivateSponsorMaxTermMonths— see Private and incognito sponsors. The ceiling rolls forward with time, so an already-valid claim stays valid; what the cap prevents is one declaration becoming a permanent opt-out. Same reasoning as SC035 forSponsorshipLicensedUntiland SC044 for a capped exemption. Not overrideable. CPM equivalent: SC054. Owner-mode equivalent: SC055. -
Syntax:
Package '{PackageId}': SponsorshipPrivateUntil='{value}' on the <PackageReference> is more than {max} months in the future (maximum {maxMonth}). Set the SponsorshipPrivateUntil attribute to {maxMonth} or earlier in: {csprojPath} Example format: <PackageReference Include="{PackageId}" Version="{version}" {platformMetadata}="{account}" SponsorshipPrivateUntil="{maxMonth}" /> -
Example:
Package 'Papyrine': SponsorshipPrivateUntil='2030-01' on the <PackageReference> is more than 12 months in the future (maximum 2027-05). Set the SponsorshipPrivateUntil attribute to 2027-05 or earlier in: /work/MyApp/MyApp.csproj Example format: <PackageReference Include="Papyrine" Version="1.0.0" GitHubSponsorAccount="octocat" SponsorshipPrivateUntil="2027-05" />
- Name: Private sponsorship end date too far in the future
- Level: Error
- Meaning: CPM equivalent of SC053.
- Syntax: Same structure as SC053 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': SponsorshipPrivateUntil='2030-01' on the <PackageVersion> in Directory.Packages.props is more than 12 months in the future (maximum 2027-05).
- Name: Private sponsorship end date too far in the future
- Level: Error
- Meaning: Owner-mode equivalent of SC053/SC054.
- Syntax:
Package '{PackageId}': {OwnerId}_SponsorshipPrivateUntil='{value}' property is more than {max} months in the future (maximum {maxMonth}).(body uses the owner-mode property remediation block.) - Example opener:
Package 'Papyrine': papyrine_SponsorshipPrivateUntil='2030-01' property is more than 12 months in the future (maximum 2027-05).
-
Name: Private sponsorship declaration expired
-
Level: Error
-
Meaning: The
SponsorshipPrivateUntilmonth has passed. Nothing about a private sponsorship can be checked against the bundled list, so the expiry is the only thing that ever re-asks the question: the build fails until someone confirms the sponsorship is still running and renews the month, or switches to another license mode. Expiry is decided at month granularity, matching SC009 and SC047 — the named month is fully covered through its final instant, and the first day of the next month is the cutoff. Fires even whenSponsorshipStartis also set: the private declaration is checked first, so an expired one fails rather than quietly falling back to the start-date path. Not overrideable. CPM equivalent: SC057. Owner-mode equivalent: SC058. -
Syntax:
Package '{PackageId}': private sponsorship declaration on the <PackageReference> expired — SponsorshipPrivateUntil='{value}' (end of month {lastDay} UTC). Confirm the private sponsorship is still active, then set the SponsorshipPrivateUntil attribute to {maxMonth} or earlier in: {csprojPath} Otherwise switch to another license mode. Example format: <PackageReference Include="{PackageId}" Version="{version}" {platformMetadata}="{account}" SponsorshipPrivateUntil="{maxMonth}" /> -
Example:
Package 'Papyrine': private sponsorship declaration on the <PackageReference> expired — SponsorshipPrivateUntil='2026-04' (end of month 2026-04-30 UTC). Confirm the private sponsorship is still active, then set the SponsorshipPrivateUntil attribute to 2027-05 or earlier in: /work/MyApp/MyApp.csproj Otherwise switch to another license mode. Example format: <PackageReference Include="Papyrine" Version="1.0.0" GitHubSponsorAccount="octocat" SponsorshipPrivateUntil="2027-05" />
- Name: Private sponsorship declaration expired
- Level: Error
- Meaning: CPM equivalent of SC056.
- Syntax: Same structure as SC056 with
<PackageVersion> in Directory.Packages.propssubstituted for<PackageReference>. - Example opener:
Package 'Papyrine': private sponsorship declaration on the <PackageVersion> in Directory.Packages.props expired — SponsorshipPrivateUntil='2026-04' (end of month 2026-04-30 UTC).
- Name: Private sponsorship declaration expired
- Level: Error
- Meaning: Owner-mode equivalent of SC056/SC057.
- Syntax:
Package '{PackageId}': private sponsorship declaration expired — {OwnerId}_SponsorshipPrivateUntil='{value}' (end of month {lastDay} UTC).(body uses the owner-mode property remediation block.) - Example opener:
Package 'Papyrine': private sponsorship declaration expired — papyrine_SponsorshipPrivateUntil='2026-04' (end of month 2026-04-30 UTC).
- Name: Private sponsorship attestation trusted
- Level: Info
- Meaning: A valid
SponsorshipPrivateUntilwas declared alongside a sponsor account: the hash check is skipped and the build passes. Private sponsorships (GitHub Sponsors) and incognito contributions (Open Collective) are deliberately excluded from the bundled hash list, so there is nothing to match and the declaration is taken on trust. Emitted as a high-priority build message rather than a warning — like SC017, the consumer's own build log is the audit trail, and a paying sponsor should not be nagged on every build for the whole term. Placement-agnostic: the same code fires for<PackageReference>,<PackageVersion>and owner-mode property placement. Not overrideable. - Syntax:
Package '{PackageId}': trusting unverified private sponsor declaration ({attempts}): SponsorshipPrivateUntil={value}, so the bundled sponsor list is not expected to contain this account. - Example:
Package 'Papyrine': trusting unverified private sponsor declaration (GitHubSponsors=octocat): SponsorshipPrivateUntil=2027-05, so the bundled sponsor list is not expected to contain this account.