dotnet/wpf · error · FileFormatException
SR.Format(SR.InvalidTransformFeatureName…
Error message
SR.Format(SR.InvalidTransformFeatureName, _fileVersion.FeatureIdentifier, _codeVersion.FeatureIdentifier)
What it means
EnsureParsed compares the feature identifier stored in the stream's version header against the identifier expected by the code's known version (_codeVersion). The comparison is case-insensitive; a mismatch means the stream belongs to a different transform, so a FileFormatException naming both identifiers is thrown.
Solutions
- Verify the file was produced by the same transform (check the two identifiers in the exception message).
- Regenerate or re-save the package with the correct tool/runtime version.
- Do not hand-edit the version header; restore the file from a trusted source.
- If supporting multiple transforms, route the stream to the correct VersionedStreamOwner based on the header identifier before parsing.
Example fix
// before: blindly opening any compound-file stream
var vs = new VersionedStreamOwner(stream, codeVersion);
vs.ReadAttempt(buffer, 0, len);
// after: pre-check the transform identity where possible, or catch and report
try { vs.ReadAttempt(buffer, 0, len); }
catch (FileFormatException e)
{ throw new InvalidDataException($"Stream transform mismatch: {e.Message}", e); } Defensive patterns
Strategy: try-catch
Type guard
static bool SameTransform(string fileFeatureId, string codeFeatureId) =>
string.Equals(fileFeatureId, codeFeatureId, StringComparison.OrdinalIgnoreCase); Try / catch
try { owner.ReadAttempt(buffer, 0, len); }
catch (FileFormatException e) { throw new InvalidDataException($"Container transform mismatch: {e.Message}", e); } Prevention
- Check the two feature identifiers in the message to identify what produced the file
- Route streams to the correct transform based on the header identifier before parsing
- Keep writer and reader transform versions in sync across deployments
When it happens
Trigger: Opening a compound-file stream whose serialized version header carries a FeatureIdentifier that does not (case-insensitively) equal the transform's expected FeatureIdentifier, during ReadAttempt/WriteAttempt/IsReadable/IsUpdatable.
Common situations: Files produced by a different compression/transform implementation or a different product version; corrupted or renamed header fields; opening a non-XPS compound file that coincidentally has a version block.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Document does not contain a package.
- Document does not contain any rights management-protected…
- File contains data in format version
- Signature structures are corrupted in this package.
- SR.Format(SR.PublishLicenseStreamHeaderTooLong, headerLen…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ff441ccd0a5dff74.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/VersionedStreamOwner.cs:400
// which the stream belongs. The "logical" stream object handed to us by the
// compound file begins -after- this stream header, so when we seek to the
// "beginning" of this stream, we are actually seeking to the location after
// the stream header, where the instance data starts.
//
BaseStream.Seek(0, SeekOrigin.Begin);
//
// The instance data starts with format version information for this transform.
//
_fileVersion = FormatVersion.LoadFromStream(BaseStream);
//
// Ensure that the feature name is as expected.
//
// NOTE: We preserve case, but do case-insensitive comparison.
if (!string.Equals(_fileVersion.FeatureIdentifier, _codeVersion.FeatureIdentifier, StringComparison.OrdinalIgnoreCase))
{
throw new FileFormatException(
SR.Format(
SR.InvalidTransformFeatureName,
_fileVersion.FeatureIdentifier,
_codeVersion.FeatureIdentifier
)
);
}
_dataOffset = BaseStream.Position;
}
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
private bool _writeOccurred; // did one of our streams get written to?View on GitHub (pinned to 81131a70a4)