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

  1. Check IsSigned before calling Countersign; if false, call Sign instead
  2. Ensure the document went through an initial signing step in your workflow
  3. Catch InvalidOperationException and inform the user the package must be signed first
  4. 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

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


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)