{"record":{"id":"31d2aa8d7805a4e4","repo":"dotnet/wpf","slug":"cannot-countersign-an-unsigned-package","errorCode":null,"errorMessage":"Cannot countersign an unsigned package.","messagePattern":"Cannot countersign an unsigned package\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/PackageDigitalSignatureManager.cs","lineNumber":573,"sourceCode":"        #endregion\n\n        #region CounterSign\n        /// <summary>\n        /// CounterSign - prompts for certificate and embeds it based on current CertificateEmbeddingOption\n        /// </summary>\n        /// <remarks>Set ParentWindow before this call if you want to make the certificate\n        /// selection dialog modal to a particular window.  Does not present the dialog if no suitable certificate \n        /// could be found in the default certificate store.\n        /// Signs all existing signature parts so that any change to these part(s) will invalidate the\n        /// returned signature.</remarks>\n        /// <exception cref=\"InvalidOperationException\">Cannot CounterSign an unsigned package.</exception>\n        /// <returns>null if no certificate could be located, or if the user cancels from the certificate selection dialog.</returns>\n        public PackageDigitalSignature Countersign()\n        {\n            // Counter-sign makes no sense if we are not already signed\n            // Check before asking for certificate\n            if (!IsSigned)\n                throw new InvalidOperationException(SR.NoCounterSignUnsignedContainer);\n\n            // prompt for certificate\n            X509Certificate certificate = PromptForSigningCertificate(ParentWindow);\n            if (certificate == null)\n                return null;\n            else\n                return Countersign(certificate);\n        }\n\n        /// <summary>\n        /// CounterSign - certificate provided\n        /// </summary>\n        /// <param name=\"certificate\">signer's certificate</param>\n        /// <exception cref=\"InvalidOperationException\">Cannot CounterSign an unsigned package.</exception>\n        /// <exception cref=\"ArgumentNullException\">certificate must be non-null.</exception>\n        /// <remarks>Signs all existing signature parts so that any change to these part(s) will invalidate the\n        /// returned signature.</remarks>\n        public PackageDigitalSignature Countersign(X509Certificate certificate)","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/PackageDigitalSignatureManager.cs#L555-L591","documentation":"The parameterless Countersign() throws InvalidOperationException (SR.NoCounterSignUnsignedContainer) when the package has no existing signatures, because countersigning by definition adds a signature over existing signatures.","triggerScenarios":"Calling Countersign() on a package that was never signed (IsSigned is false), or on a freshly created package with no signature parts.","commonSituations":"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.","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"],"exampleFix":"// before\nmgr.Countersign(); // fails if package unsigned\n// after\nif (mgr.IsSigned)\n    mgr.Countersign();\nelse\n    mgr.Sign(parts, cert);","handlingStrategy":"validation","validationCode":"if (!manager.IsSigned)\n    throw new InvalidOperationException(\"Package must be signed before countersigning.\");","typeGuard":null,"tryCatchPattern":"try { manager.Countersign(); }\ncatch (InvalidOperationException ex) { log.Warn(\"Countersign skipped: package unsigned\", ex); manager.Sign(parts, cert); }","preventionTips":["Gate countersign UI/actions on IsSigned","Verify the initial signing step completed (and persisted) before countersign","Check signatures survived save/reload round-trips"],"tags":["wpf","packaging","invalidoperationexception","countersign"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}