dotnet/wpf · error · XpsPackagingException

FixedPage has more than one related story fragment.

Error message

FixedPage has more than one related story fragment.

What it means

XpsPackagingException thrown by XpsFixedPageReaderWriter.AddStoryFragment when the page already has a StoryFragment. The XPS spec allows at most one StoryFragments part per FixedPage, so a second AddStoryFragment call is rejected. This keeps the package valid for consumers that read story (reading-order) data.

Solutions

  1. Call AddStoryFragment only once per page; write all story content into the single returned XpsStoryFragments writer.
  2. Check page.StoryFragment for null before calling AddStoryFragment and reuse the existing writer.
  3. Restructure so one page holds one story fragment; split content across pages if more fragments are needed.
  4. If merging templates, strip pre-existing StoryFragments parts before adding your own.
  5. Handle XpsPackagingException in batch pipelines to flag over-fragmented pages.

Example fix

// before
var frag1 = page.AddStoryFragment();
var frag2 = page.AddStoryFragment(); // throws
// after
var frag = page.StoryFragment ?? page.AddStoryFragment();
frag.AddStory(...); // all stories in one fragment
frag.Commit();
Defensive patterns

Strategy: validation

Validate before calling

// Check before adding
if (pageWriter.StoryFragment != null)
{
    var existing = pageWriter.StoryFragment; // reuse it
}
else
{
    var frag = pageWriter.AddStoryFragment();
}

Type guard

bool HasStoryFragment(IXpsFixedPageReaderWriter page) => page.StoryFragment != null;

Try / catch

try
{
    var frag = pageWriter.AddStoryFragment();
}
catch (XpsPackagingException ex) when (ex.Message.Contains("StoryFragment"))
{
    var existing = pageWriter.StoryFragment; // fall back to existing fragment
}

Prevention

When it happens

Trigger: Calling pageWriter.AddStoryFragment() twice on the same fixed page — commonly when generating story fragments in a loop per section but the page object is reused, or when a document template already attached a StoryFragment and generator code adds another.

Common situations: Document generators that produce multiple story sections and assume a new fragment per section; merging content from templates that already contain StoryFragments; refactored code paths where an earlier call to AddStoryFragment was forgotten.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsFixedPageReaderWriter.cs:853

                _metroPart.CreateRelationship(new Uri(resourcePath, UriKind.Relative),
                                           TargetMode.Internal,
                                           XpsS0Markup.ResourceRelationshipName);
}

            return xpsResource;
        }

        /// <summary>
        /// </summary>
        public
        XpsStructure
        AddStoryFragment(
            )
        {
            if (this.StoryFragment != null)
            {
                // StoryFragments already available for this FixedPage
                throw new XpsPackagingException(SR.ReachPackaging_MoreThanOneStoryFragment);
            }

            Uri pageUri = this.CurrentXpsManager.CreateFragmentUri(PageNumber);
            //
            // Create the part and writer
            //
            PackagePart metroPart = this.CurrentXpsManager.GeneratePart(
                        XpsS0Markup.StoryFragmentsContentType,
                        pageUri);

            _storyFragment = new XpsStructure(CurrentXpsManager, this, metroPart);

            //
            // Create the relationship between the document and the document-structure
            // Not in INode.Flush because IXpsFixedPageReader has no commit.
            //
            string storyFragmentPath = XpsManager.MakeRelativePath(this.Uri, _storyFragment.Uri);

View on GitHub (pinned to 81131a70a4)