dotnet/wpf · error · ArgumentException

SR.NotAValidRelationshipPartUri

Error message

SR.NotAValidRelationshipPartUri

What it means

ArgumentException with message SR.NotAValidRelationshipPartUri thrown by PackUriHelper.IsRelationshipUri. A pack URI whose part name ends in '.rels' and also contains an upper-case '_rels' segment as the third-last segment is not a valid relationship part name, because '_rels' segments may only appear immediately before the '/xxx.rels' leaf.

Solutions

  1. Build part URIs with PackUriHelper.CreatePartUri instead of manual strings.
  2. Fix the URI so '_rels' appears only as the segment immediately preceding the '.rels' leaf.
  3. Validate the URI with PackUriHelper.IsRelationshipPartUri / ValidatedPartUri before use.
  4. Repair or regenerate the offending package with the Open XML SDK or a known-good producer.

Example fix

// before
var uri = new Uri("/word/_rels/document/_rels/document.xml.rels", UriKind.Relative);
// after
var partUri = PackUriHelper.CreatePartUri(new Uri("/word/document.xml", UriKind.Relative));
var relsUri = PackUriHelper.GetRelationshipPartUri(partUri); // /word/_rels/document.xml.rels
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidRelsUri(Uri u) => !u.ToString().Contains("_rels/") || PackUriHelper.IsRelationshipPartUri(u);

Try / catch

try { partUri = PackUriHelper.ValidatedPartUri(uri); }
catch (ArgumentException) { /* log malformed pack URI, reject package */ }

Prevention

When it happens

Trigger: Calling PackUriHelper.ValidatedPartUri (or CreatePartUri/GetRelationshipPartUri) with a pack URI like '/a/_rels/b/_rels/c.rels' — i.e., a .rels part nested under another _rels folder, or upper-case _rels segments misplaced in the path.

Common situations: Constructing part URIs by string concatenation instead of PackUriHelper APIs; OPC packages produced by non-.NET tools with malformed '_rels' placement; migrating packages between formats that lowercase/uppercase segment names.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/f4eac774c250a65d. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/PackUriHelper.cs:511

                // must be at least two segments and the last one must end with .RELs
                // and the length of the segment should be greater than just the extension.
                if ((segments.Length >= 3) &&
                    (segments[segments.Length - 1].Length > _relationshipPartExtensionName.Length))
                {
                    // look for "_RELS" segment which must be second last segment
                    result = string.Equals(segments[segments.Length - 2], _relationshipPartUpperCaseSegmentName, StringComparison.Ordinal);
                }

                // In addition we need to make sure that the relationship is not created by taking another relationship
                // as the source of this uri. So XXX/_rels/_rels/YYY.rels.rels would be invalid.
                if (segments.Length > 3 && result)
                {
                    if ((segments[segments.Length - 1]).EndsWith(_relsrelsUpperCaseExtension, StringComparison.Ordinal))
                    {
                        // look for "_rels" segment in the third last segment
                        if(string.Equals(segments[segments.Length - 3], _relationshipPartUpperCaseSegmentName, StringComparison.Ordinal))
                            throw new ArgumentException(SR.NotAValidRelationshipPartUri);
                    }
                }

                return result;
            }

            //Returns the normalized string for the part uri.            
            //Currently normalizing the PartUriString consists of only one step - 
            //1. Take the wellformed and escaped partUri string and case fold to UpperInvariant            
            private string GetNormalizedPartUriString()
            {
                //Case Fold the partUri string to Invariant Upper case (this helps us perform case insensitive comparison)
                //We follow the Simple case folding specified in the Unicode standard

                if (_isNormalized)
                    return _partUriString;
                else
                    return _partUriString.ToUpperInvariant();

View on GitHub (pinned to 81131a70a4)