dotnet/wpf · error · FileFormatException

SR.WrongDocumentPropertyVariantType (propId, fmtid, actual…

Error message

SR.WrongDocumentPropertyVariantType (propId, fmtid, actual vt, expected vt)

What it means

FileFormatException with message WrongDocumentPropertyVariantType(propId, fmtid, actual vt, expected vt) thrown by StorageBasedPackageProperties.GetOleProperty when an OLE compound-file property (e.g. document Title or Keywords) is read and its stored VARTYPE differs from the VARTYPE the caller requested. The package-properties reader treats the type mismatch as a corrupt/invalid property stream rather than coercing.

Solutions

  1. Open the document in a compliant producer and re-save to normalize the property types.
  2. Inspect the OLE property set (fmtid/propId) with a tool like PropBadge or Open XML SDK to confirm the stored vt.
  3. Wrap property reads in try-catch for FileFormatException and treat as missing metadata.
  4. If you control writing code, use the same VARTYPE the reader expects for each propId.

Example fix

// before
string title = package.PackageProperties.Title; // throws on vt mismatch
// after
string title;
try { title = package.PackageProperties.Title; }
catch (FileFormatException) { title = null; }
Defensive patterns

Strategy: try-catch

Try / catch

try { title = pkg.PackageProperties.Title; }
catch (FileFormatException ex) when (ex.Message.Contains("variant type") || ex.Message.Contains("WrongDocumentPropertyVariantType")) { title = null; }

Prevention

When it happens

Trigger: Reading package properties (PackageProperties.Title/Subject/Creator/Keywords/Description/LastModifiedBy) from a document whose OLE property set stores the property with a different variant type than expected — e.g. VT_LPWSTR stored where VT_LPSTR is expected for that propId, or an integer where a string is required.

Common situations: Documents produced by third-party generators that write non-standard property types; files edited by older/other office suites with divergent property-set encoding; corrupted SummaryInformation streams.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/StorageBasedPackageProperties.cs:531

            object obj = null;

            PROPSPEC[] propSpecs = new PROPSPEC[1];
            PROPVARIANT[] vals = new PROPVARIANT[1];

            propSpecs[0].propType = (uint)PropSpecType.Id;
            propSpecs[0].union.propId = propId;

            VARTYPE vtExpected = GetVtFromPropId(fmtid, propId);

            int hresult = ps.ReadMultiple(1, propSpecs, vals);

            if (hresult == SafeNativeCompoundFileConstants.S_OK)
            {
                try
                {
                    if (vals[0].vt != vtExpected)
                    {
                        throw new FileFormatException(
                                        SR.Format(
                                            SR.WrongDocumentPropertyVariantType,
                                            propId,
                                            fmtid.ToString(),
                                            vals[0].vt,
                                            vtExpected
                                            )
                                        );
                    }

                    switch (vals[0].vt)
                    {
                        case VARTYPE.VT_LPSTR:
                            //
                            // We store string properties as CP_ACP or UTF-8. 
                            // But no matter which format the string was encoded, we always use the UTF-8
                            // encoder/decoder to decode the byte array, because the UTF-8 code of an ASCII
                            // string is the same as the ASCII string.

View on GitHub (pinned to 81131a70a4)