dotnet/wpf · error · InvalidOperationException

SR.ParserMultiBamls

Error message

SR.ParserMultiBamls

What it means

BamlRecords' SetWriteCache (used by GetPropertyStartRecordType record management) throws InvalidOperationException(SR.ParserMultiBamls) when a BamlRecord that is not pinned is written to a cache slot that already holds a record — the write-cache assumes each record type appears once. The Debug.Assert shows this is an internal invariant; the throw is the release-mode fallback.

Solutions

  1. Use a fresh BamlRecordManager/writer per document; do not share record caches across BAML streams
  2. Ensure each record is Pinned before reuse across multiple writes
  3. This is framework-internal — if hit via public APIs, file a bug with a minimal XAML-to-BAML repro
  4. Check for reentrancy: nested/concurrent serialization using the same writer

Example fix

// before: shared record manager across documents
var rm = new BamlRecordManager(); WriteBaml(doc1, rm); WriteBaml(doc2, rm);
// after: one manager per document
WriteBaml(doc1, new BamlRecordManager()); WriteBaml(doc2, new BamlRecordManager());
Defensive patterns

Strategy: validation

Validate before calling

// never share a BamlRecordManager/writer across documents
if (recordManager.InUse) throw new InvalidOperationException("Record manager already in use for another BAML");

Try / catch

try { WriteBaml(doc, recordManager); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Baml")) {
    recordManager = new BamlRecordManager(); // recreate and retry once
}

Prevention

When it happens

Trigger: BAML writer/record-manager encounters a second non-pinned record of the same RecordType while the cache slot is still occupied — during multi-BAML assembly/serialization bookkeeping.

Common situations: Writing multiple BAML documents concurrently or sequentially through shared record caches, framework-internal record-manager misuse, or custom tooling that reuses BamlRecordManager across documents without clearing it.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/BamlRecords.cs:769

        //  ReleaseWriteRecord
        //
        //  Frees a record originally claimed with GetWriteRecord. Note that records in the
        //  read cache are implicitly recycled, and records in the write cache are explicitly
        //  recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord).
        //
        //+---------------------------------------------------------------------------------------------

        internal void ReleaseWriteRecord(BamlRecord record)
        {
            // Put the write record back into the cache, if we're allowed to recycle it.

            if( !record.IsPinned )
            {
                Debug.Assert(null == _writeCache[(int)record.RecordType]);
                if (null != _writeCache[(int)record.RecordType])
                {
                    // This is really an internal error.
                    throw new InvalidOperationException(SR.ParserMultiBamls);
                }
                _writeCache[(int)record.RecordType] = record;
            }
        }


        // Cache of BamlRecords, used during read, to avoid lots of records from being
        // created.  If a record gets pinned (BamlRecord.IsPinned gets set), it is not re-used.

#if !PBTCOMPILER
        private BamlRecord[] _readCache = new BamlRecord[(int)BamlRecordType.LastRecordType];
#endif

        // Cache of BamlRecords, used during write, also to avoid lots of records
        // from being created.

        private BamlRecord[] _writeCache = null; //new BamlRecord[(int)BamlRecordType.LastRecordType];
    }

View on GitHub (pinned to 81131a70a4)