dotnet/wpf · error · ArgumentException
Packed button length not equal to expected length
Error message
Packed button length not equal to expected length
What it means
Thrown by StrokeSerializer.SavePackets (invoked from cbWrite) when packing stroke button data for ISF output: the BitWriter produced a byte array whose length differs from the computed expected size (buttonCount*pointCount+7)/8. This is an internal invariant check during serialization.
Solutions
- Verify any custom Stroke/StrokeData construction sets button counts and point counts consistently
- Use standard StylusPointCollection-based strokes rather than hand-built packet data
- If extending ink serialization, ensure buttonCount matches the actual button bits written
- Report as a bug if hit with stock StrokeCollection data
Example fix
// before var stroke = new CustomStroke(rawPacketData); // buttonCount mismatch // after var stroke = new Stroke(new StylusPointCollection(points));
Defensive patterns
Strategy: validation
Validate before calling
// Ensure stroke was built from a StylusPointCollection, not raw packet data bool WellFormedStroke(Stroke s) => s != null && s.StylusPoints != null && s.StylusPoints.Count > 0;
Type guard
bool WellFormedStroke(Stroke s) => s?.StylusPoints?.Count > 0;
Try / catch
try { stream.Save(ms); }
catch (ArgumentException ex) { throw new InvalidOperationException("Stroke serialization invariant broken", ex); } Prevention
- Construct strokes via StylusPointCollection, not hand-built packet tables
- If subclassing Stroke, keep button/point counts consistent
- Report framework bugs if hit with stock strokes
- Serialize only strokes originating from real stylus input or validated data
When it happens
Trigger: Saving a StrokeCollection to ISF where a Stroke's button data has an internal length inconsistent with its packet description — usually only reachable with programmatically constructed/extended Stroke data.
Common situations: Custom stroke subclasses overriding drawing attributes or packet data incorrectly, ink data built by interop code with mismatched button counts.
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
- Invalid EP in ISF
- Property data must be a non-reference variant compatible…
- Read different size from stream then expected
- ROP data size was not found
- ROP data was incorrectly serialized
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/afa1a5ea33967533.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/StrokeSerializer.cs:905
//
if (bitsToWrite > 0)
{
bitWriter.Write(byteOfButtonData, bitsToWrite);
}
if (fullBytesForButtonsPerPacket > 0)
{
bitsToWrite = Native.BitsPerByte;
}
}
}
// retrieve the button bytes
byte[] packedButtonData = bitWriter.ToBytes();
if (packedButtonData.Length !=
((buttonCount * pointCount + 7) / Native.BitsPerByte))
{
throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Packed button length not equal to expected length"));
}
// write out the packed button data to the output stream
stream.Write(packedButtonData, 0, packedButtonData.Length);
localBytesWritten += (uint)packedButtonData.Length;
}
*/
return localBytesWritten;
}
#if OLD_ISF
/// <summary>
/// Saves the packets data corresponding to a packet property (identified by the guid) into the stream
/// based on the Compression algorithm and compress header
/// </summary>
/// <param name="packetdata">packet data to save</param>
/// <param name="stream">null to calculate only the size</param>
/// <param name="compressor"></param>View on GitHub (pinned to 81131a70a4)