Skip to content

[BUG] DICOM channels with a filter/transformer fail with IllegalStateException: state:EXPECT_FRAG on private undefined-length sequences #430

Description

@jessesaga

Describe the bug

Any DICOM-typed connector that has a filter or transformer attached fails to process messages containing an undefined-length sequence under a private tag that dcm4che2 resolves to VR UN (implicit VR, tag not in its dictionary). Common real-world producers: FujiFILM (0029,E131) and Siemens MEDCOM (0029,1140). Messages with no filter/transformer pass through fine, because they never go through the XML round trip.

com.mirth.connect.donkey.model.message.MessageSerializerException: Error converting XML to DICOM
Caused by: java.lang.IllegalStateException: state:EXPECT_FRAG
        at org.dcm4che2.io.ContentHandlerAdapter.startElement(...)
        at com.mirth.connect.plugins.datatypes.dicom.DICOMSerializer.fromXML(...)

Root cause

dcm4che2 2.0.29's XML round trip is asymmetric:

  • DicomInputStream reads a UN element with undefined length whose items hold dataset elements and represents it as SQ in memory.
  • toXML uses the streaming SAXWriter, which emits the wire VR: <tag0029E131 vr="UN" len="-1"> with structured <item> children.
  • fromXML hands that to ContentHandlerAdapter, which only enters its sequence state for vr="SQ" and otherwise expects fragments; the first <attr> inside the item throws state:EXPECT_FRAG.

dcm4che2 has had no release since 2015, so this cannot be fixed at the library.

To Reproduce

Programmatic, no fixtures needed (this is what the accompanying test does):

  1. Build a BasicDicomObject, putNestedDicomObject(0x0029E131, item) with any element in the item, write it as Implicit VR Little Endian.
  2. new DICOMSerializer().toXML(base64) — note the output carries vr="UN" with an <item> child.
  3. fromXML(thatXml) throws.

Or in a running engine: DICOM Listener → any transformer step → send a Fuji or Siemens CR/CT object carrying a private sequence.

Expected behavior

fromXML accepts the XML toXML produced, and the re-encoded DICOM is identical to what the engine emits without a transformer.

Proposed fix

Reader-side, in DICOMSerializer.fromXML's existing DOM pre-pass (the one that renames <tagXXXXXXXX> back to <attr>): when an element's <item> children contain renamed <attr> elements, set vr="SQ" before the SAX parse. That is the same content-based decision DicomInputStream makes for the binary form. toXML output is unchanged, so transformer scripts see identical XML; fragment containers (encapsulated pixel data) are untouched; every input that parses today produces an identical DicomObject; and the rewrite is a no-op if a future dcm4che emits SQ itself.

Verified byte-for-byte that the transformer round trip now produces the same DICOM as the no-transformer pass-through path, for implicit and explicit VR LE. PR to follow.

Environment

  • OIE main at 423df18 (also reproduces on 4.6.0-based builds)
  • dcm4che2 2.0.29 as bundled

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions