dotnet/wpf · error · ArgumentException
Duplicates not allowed - signature part already exists.
Error message
Duplicates not allowed - signature part already exists.
What it means
Before writing a new signature, Sign generates a signature part name and throws ArgumentException (SR.DuplicateSignature) if a part with that URI already exists in the package, to avoid overwriting or duplicating an existing signature part.
Solutions
- Remove leftover signature parts (via DeletePart) from the failed attempt before re-signing
- Inspect and clean the package's /_rels/DigitalSignatures and signature origin parts after a failed sign
- Recreate the package from source if its signature parts are in a corrupted state
- Catch ArgumentException and offer the user a 'repair package then re-sign' path
Example fix
// before
mgr.Sign(parts, cert); // retry after earlier failure -> duplicate signature part
// after
var existing = mgr.Signatures.Select(s => s.SignaturePart.Uri).ToList();
foreach (var uri in existing)
pkg.DeletePart(uri);
mgr.Sign(parts, cert); Defensive patterns
Strategy: try-catch
Validate before calling
Uri next = /* generated name */;
if (package.PartExists(next))
package.DeletePart(next); // clean leftover from failed attempt Try / catch
try { manager.Sign(parts, cert); }
catch (ArgumentException ex) { log.Error("Duplicate signature part", ex); /* cleanup and retry */ } Prevention
- After a failed sign, delete orphaned signature/origin parts before retrying
- Avoid mutating signature parts manually inside the package
- Serialize signing operations so concurrent signs cannot collide on part names
When it happens
Trigger: A previous Sign call failed midway and left a pre-created signature/origin part behind; the generated signature part name collides with an existing part; signing the same package twice with deterministic naming where cleanup never happened.
Common situations: Retrying a failed sign operation on the same package without removing leftover parts; a crashed process leaving half-written signature parts; manually renaming or copying signature parts in the package.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Can only countersign parts with Digital Signature…
- Must specify an item to sign.
- Parameter cannot be a zero-length string.
- SR.TransformStackValid
- The given data space label name is already in use.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/5232b078ae71761a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/PackageDigitalSignatureManager.cs:463
throw new InvalidOperationException(SR.CannotSignReadOnlyFile);
VerifySignArguments(parts, certificate, relationshipSelectors, signatureId, signatureObjects, objectReferences);
// substitute default id if none given
if (string.IsNullOrEmpty(signatureId))
{
signatureId = "packageSignature"; // default
}
// Make sure the list reflects what's in the package.
// Do this before adding the new signature part because we don't want it included until it
// is fully formed (and delaying the add saves us having to remove it in case there is an
// error during the Sign call).
EnsureSignatures();
Uri newSignaturePartName = GenerateSignaturePartName();
if (_container.PartExists(newSignaturePartName))
throw new ArgumentException(SR.DuplicateSignature);
// Pre-create origin part if it does not already exist.
// Do this before signing to allow for signing the package relationship part (because a Relationship
// is added from the Package to the Origin part by this call) and the Origin Relationship part in case this is
// a Publishing signature and the caller wants the addition of more signatures to break this signature.
PackageRelationship relationshipToNewSignature = OriginPart.CreateRelationship(newSignaturePartName, TargetMode.Internal,
_originToSignatureRelationshipType);
_container.Flush(); // ensure the origin relationship part is persisted so that any signature will include this newest relationship
VerifyPartsExist(parts);
// sign the data and optionally embed the certificate
bool embedCertificateInSignaturePart = (_certificateEmbeddingOption == CertificateEmbeddingOption.InSignaturePart);
// convert cert to version2 - more functionality
if (certificate is not X509Certificate2 exSigner)
exSigner = new X509Certificate2(certificate.Handle);
View on GitHub (pinned to 81131a70a4)