{"record":{"id":"44232e0f57dfcca7","repo":"dotnet/wpf","slug":"cannot-sign-read-only-file","errorCode":null,"errorMessage":"Cannot sign read-only file.","messagePattern":"Cannot sign read-only file\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/PackageDigitalSignatureManager.cs","lineNumber":445,"sourceCode":"        /// tags, it follows that this Manifest tag must include at least one Reference tag.\n        /// This means that every signature include at least one of a Part to sign (non-empty parts tag)\n        /// or a Relationship to sign (non-empty relationshipSelectors) even if such a signature\n        /// is only destined to sign signatureObjects and/or objectReferences.\n        /// This overload provides support for generation of Xml signatures that require custom\n        /// Object tags.  For any provided Object tag to be signed, a corresponding Reference\n        /// tag must be provided with a Uri that targets the Object tag using local fragment \n        /// syntax.  If the object had an ID of \"myObject\" the Uri on the Reference would\n        /// be \"#myObject\".  For unsigned objects, no reference is required.</remarks>\n        public PackageDigitalSignature Sign(\n            IEnumerable<Uri> parts, \n            X509Certificate certificate,\n            IEnumerable<PackageRelationshipSelector> relationshipSelectors,\n            String signatureId,\n            IEnumerable<System.Security.Cryptography.Xml.DataObject> signatureObjects,\n            IEnumerable<System.Security.Cryptography.Xml.Reference> objectReferences)\n        {\n            if (ReadOnly)\n                throw new InvalidOperationException(SR.CannotSignReadOnlyFile);\n\n            VerifySignArguments(parts, certificate, relationshipSelectors, signatureId, signatureObjects, objectReferences);\n\n            // substitute default id if none given\n            if (string.IsNullOrEmpty(signatureId))\n            {\n                signatureId = \"packageSignature\";   // default\n            }\n\n            // Make sure the list reflects what's in the package.\n            // Do this before adding the new signature part because we don't want it included until it\n            // is fully formed (and delaying the add saves us having to remove it in case there is an \n            // error during the Sign call).\n            EnsureSignatures();\n\n            Uri newSignaturePartName = GenerateSignaturePartName();\n            if (_container.PartExists(newSignaturePartName))\n                throw new ArgumentException(SR.DuplicateSignature);","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/PackageDigitalSignatureManager.cs#L427-L463","documentation":"Sign throws InvalidOperationException (SR.CannotSignReadOnlyFile) when the package was opened in read-only mode, because signing requires writing the signature part and digital signature origin part back into the package.","triggerScenarios":"Creating a Package or the manager from a stream/file opened FileAccess.Read or PackageOpenMode.ReadOnly and then calling any Sign/Countersign overload.","commonSituations":"Opening a package from a stream that was opened with FileAccess.Read; consuming a signed package from disk without write permission and then attempting to re-sign; opening from a read-only network share or embedded resource stream.","solutions":["Open the package with PackageOpenMode.ReadWrite (or FileAccess.ReadWrite) before signing","Ensure the underlying file/stream and its directory grant write permission","If the package is only for consumption, do not call Sign — check ReadOnly property first and skip signing","Copy the read-only package to a writable location and reopen ReadWrite if you must sign it"],"exampleFix":"// before\nusing (Package pkg = Package.Open(path, FileMode.Open, FileAccess.Read))\n{\n    var mgr = new PackageDigitalSignatureManager(pkg);\n    mgr.Sign(parts, cert); // throws: package is read-only\n}\n// after\nusing (Package pkg = Package.Open(path, FileMode.Open, FileAccess.ReadWrite))\n{\n    var mgr = new PackageDigitalSignatureManager(pkg);\n    if (!mgr.ReadOnly)\n        mgr.Sign(parts, cert);\n}","handlingStrategy":"validation","validationCode":"if (manager.ReadOnly)\n    throw new InvalidOperationException(\"Open the package with ReadWrite access before signing.\");","typeGuard":null,"tryCatchPattern":"try { manager.Sign(parts, cert); }\ncatch (InvalidOperationException ex) when (manager.ReadOnly) { log.Error(\"Package is read-only\", ex); }","preventionTips":["Always open packages with FileAccess.ReadWrite when signing is expected","Check PackageDigitalSignatureManager.ReadOnly before sign operations","Verify file/share permissions in deployment environments"],"tags":["wpf","packaging","invalidoperationexception","read-only"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}