dotnet/wpf · error · ArgumentException

Global Custom Attribute tag embedded in ISF stream does not…

Error message

Global Custom Attribute tag embedded in ISF stream does not match guid table

What it means

While decoding an ISF stream, a Global Custom Attribute (extended property) tag was encountered whose tag index does not map to any GUID in the current guid table. The library cannot resolve which property the data belongs to, so it rejects the stream with ArgumentException.

Solutions

  1. Ensure the application that serializes the ink and the one that deserializes it share the same custom extended-property GUID registrations.
  2. Use the same .NET/WPF version on both ends, or strip unknown custom attributes before transfer.
  3. Check the stream for corruption or third-party ISF extensions; re-export from the original source.
  4. Catch ArgumentException around DecodeISF and fall back to loading the strokes without the custom attributes where possible.

Example fix

// before
collection = serializer.DecodeISF(stream);
// after
try { collection = serializer.DecodeISF(stream); }
catch (ArgumentException e) {
    log.Warn("ISF custom attribute not in guid table: " + e.Message);
    collection = DecodeCoreStrokesOnly(stream); // tolerant path
}
Defensive patterns

Strategy: validation

Validate before calling

// Confirm both ends register the same custom extended-property GUIDs before transfer
if (!knownGuidTable.Contains(customGuid)) log.Warn("Custom ISF attribute {guid} unknown to reader", customGuid);

Type guard

static bool HasKnownGuid(Guid g, IReadOnlyCollection<Guid> table) => table.Contains(g);

Try / catch

try { serializer.DecodeISF(stream); }
catch (ArgumentException ex) when (ex.Message.Contains("guid table")) { return DecodeWithoutCustomAttributes(stream); }

Prevention

When it happens

Trigger: DecodeISF/DecodeRawISF reads a custom-attribute tag whose FindGuid lookup in the guidList returns Guid.Empty — i.e., the stream references a custom GUID tag not present in the decoder's known/registered guid table.

Common situations: ISF written by a newer WPF version or third-party vendor with custom extended properties that the consuming app's guid table lacks; stream crossed process/machine boundaries with different registered custom attributes; hand-crafted or fuzzed ISF payloads.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/InkSerializer.cs:741

                            // Load the Index into the Stroke Descriptor Table which will be used by the stroke following this till
                            // a next different Index is found
                            bytesDecodedInCurrentTag = SerializationHelper.Decode(inputStream, out strokeDescriptorTableIndex);
                            break;
                        }

                    default:
                        {
                            if ((uint)isfTag >= KnownIdCache.CustomGuidBaseIndex || ((uint)isfTag >= KnownTagCache.KnownTagCount && ((uint)isfTag < (KnownTagCache.KnownTagCount + KnownIdCache.OriginalISFIdTable.Length))))
                            {
                                ISFDebugTrace("  CUSTOM_GUID=" + guidList.FindGuid(isfTag).ToString());

                                // Loads any custom property data
                                bytesDecodedInCurrentTag = remainingBytesInStream;

                                Guid guid = guidList.FindGuid(isfTag);
                                if (guid == Guid.Empty)
                                {
                                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Global Custom Attribute tag embedded in ISF stream does not match guid table"), "inkdata");
                                }


                                object data;

                                // load the custom property data from the stream (and decode the type)
                                localBytesDecoded = ExtendedPropertySerializer.DecodeAsISF(inputStream, bytesDecodedInCurrentTag, guidList, isfTag, ref guid, out data);
                                if (localBytesDecoded > bytesDecodedInCurrentTag)
                                {
                                    throw new ArgumentException(ISFDebugMessage("Invalid ISF data"), "inkdata");
                                }


                                // add the guid/data pair into the property collection (don't redecode the type)
                                _coreStrokes.ExtendedProperties[guid] = data;
                            }
                            else
                            {

View on GitHub (pinned to 81131a70a4)