dotnet/wpf · error · InvalidOperationException
Cannot countersign an unsigned package.
Error message
Cannot countersign an unsigned package.
What it means
The parameterless Countersign() throws InvalidOperationException (SR.NoCounterSignUnsignedContainer) when the package has no existing signatures, because countersigning by definition adds a signature over existing signatures.
Solutions
- Check IsSigned before calling Countersign; if false, call Sign instead
- Ensure the document went through an initial signing step in your workflow
- Catch InvalidOperationException and inform the user the package must be signed first
- Verify signatures were not deleted by a prior save/copy operation
Example fix
// before
mgr.Countersign(); // fails if package unsigned
// after
if (mgr.IsSigned)
mgr.Countersign();
else
mgr.Sign(parts, cert); Defensive patterns
Strategy: validation
Validate before calling
if (!manager.IsSigned)
throw new InvalidOperationException("Package must be signed before countersigning."); Try / catch
try { manager.Countersign(); }
catch (InvalidOperationException ex) { log.Warn("Countersign skipped: package unsigned", ex); manager.Sign(parts, cert); } Prevention
- Gate countersign UI/actions on IsSigned
- Verify the initial signing step completed (and persisted) before countersign
- Check signatures survived save/reload round-trips
When it happens
Trigger: Calling Countersign() on a package that was never signed (IsSigned is false), or on a freshly created package with no signature parts.
Common situations: UI flows that allow a countersign button on unsigned documents; a package whose signatures were removed before countersigning; calling Countersign instead of Sign by mistake.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Can only countersign parts with Digital Signature…
- Cannot sign read-only file.
- ' ' cannot contain the path delimiter: ' '.
- ' ' cannot start with the reserved character range…
- ' ' ID is not a valid XSD ID.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/31d2aa8d7805a4e4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/PackageDigitalSignatureManager.cs:573
#endregion
#region CounterSign
/// <summary>
/// CounterSign - prompts for certificate and embeds it based on current CertificateEmbeddingOption
/// </summary>
/// <remarks>Set ParentWindow before this call if you want to make the certificate
/// selection dialog modal to a particular window. Does not present the dialog if no suitable certificate
/// could be found in the default certificate store.
/// Signs all existing signature parts so that any change to these part(s) will invalidate the
/// returned signature.</remarks>
/// <exception cref="InvalidOperationException">Cannot CounterSign an unsigned package.</exception>
/// <returns>null if no certificate could be located, or if the user cancels from the certificate selection dialog.</returns>
public PackageDigitalSignature Countersign()
{
// Counter-sign makes no sense if we are not already signed
// Check before asking for certificate
if (!IsSigned)
throw new InvalidOperationException(SR.NoCounterSignUnsignedContainer);
// prompt for certificate
X509Certificate certificate = PromptForSigningCertificate(ParentWindow);
if (certificate == null)
return null;
else
return Countersign(certificate);
}
/// <summary>
/// CounterSign - certificate provided
/// </summary>
/// <param name="certificate">signer's certificate</param>
/// <exception cref="InvalidOperationException">Cannot CounterSign an unsigned package.</exception>
/// <exception cref="ArgumentNullException">certificate must be non-null.</exception>
/// <remarks>Signs all existing signature parts so that any change to these part(s) will invalidate the
/// returned signature.</remarks>
public PackageDigitalSignature Countersign(X509Certificate certificate)View on GitHub (pinned to 81131a70a4)