A PACS operator kicks off what looks like a simple retrieval: pull a prior study out of the archive and send it to a teleradiology partner’s viewer. The archive accepts the request and then goes quiet. Its final response is a status of Failure, carrying a list of every instance it could not deliver.
The archive isn’t stuck and the network isn’t down. C-MOVE, the DICOM operation behind that request, never intended to hand the study back to whoever asked for it. It told the archive to open a second connection to the destination and push the study there. That destination’s firewall never let the connection in.
The Query/Retrieve Service Class, in One Sentence
C-MOVE is one of three operations inside DICOM’s Query/Retrieve Service Class, the part of the standard that lets one system search another’s holdings and pull studies out of them. The standard is specific about the split: SOP Classes of the Query/Retrieve Service Class “are implemented using the DIMSE-C C-FIND, C-MOVE, and C-GET services”, each covering a different part of the job. This piece stays on the three operations themselves, and on the one that trips up more integrators than the other two combined.
| Operation | What it does | Where the data goes |
|---|---|---|
| C-FIND | Searches for matching studies, series, or instances | Nowhere. Returns metadata only |
| C-MOVE | Instructs the archive to send matching instances to a named destination | The one AE named in Move Destination, over a separate connection |
| C-GET | Requests matching instances be sent back to the requester | The requester itself, over the same connection |
C-FIND Finds. It Doesn’t Fetch
A C-FIND query never moves a study. It matches the keys in the request, patient ID, study date, accession number, against what the archive holds, and returns an identifier for each hit. One of the attributes that identifier can carry is Retrieve AE Title.
The standard is explicit about what that field means: the Application Entity named there “shall support either the C-GET or C-MOVE SOP Class of the Query/Retrieve Service Class.” In other words, finding a study and being told where it lives is one operation. Actually pulling it is a separate one, and that separation is where C-MOVE and C-GET diverge.
C-MOVE: A Retrieval That Isn’t a Retrieval
The name suggests the requester gets the study. It doesn’t, not necessarily. A C-MOVE request carries a Move Destination attribute, and the standard defines it plainly: it “specifies the Application Entity Title of the receiver of the C-STORE sub-operations.” One title, singular: the requester can name itself or name a completely different system, but it names exactly one.
What happens next is the part that catches people off guard. The standard requires that the transfer run on its own connection: “The C-STORE sub-operations shall always be accomplished over an Association different from the Association that accomplishes the C-MOVE operation. Hence, the SCP of the Query/Retrieve Service Class serves as the SCU of the Storage Service Class.”
So the archive turns around and connects to the AE named in Move Destination, reusing a compatible association if it has one and opening a new one if it doesn’t. It pushes the study over as if it were initiating a fresh transfer of its own. A note attached to the same section is careful about who that AE can be: “The application entity that receives the stored SOP Instances may or may not be the originator of the C-MOVE operation.”
That’s three roles in a single exchange: the system asking for the move, the archive fulfilling it, and the destination that has to be ready to receive a connection it did nothing to start. Three roles do not have to mean three systems. The requester and the destination can be the same box, which changes the address book and nothing else.
Why That Makes C-MOVE Firewall-Hostile
Most network requests follow a pattern firewalls are built around: one side opens a connection, the other answers on it, and nothing unsolicited shows up anywhere. C-MOVE breaks that pattern even when the destination is the requester. Naming yourself in Move Destination changes who ends up holding the study, not the rule that the C-STORE sub-operations run on a separate association the archive initiates. Move a study to yourself and you still need a Storage SCP listening on a known port, with a firewall rule that lets the archive reach it.
The archive reaches the Move Destination cold, on a connection that AE’s network layer never asked for. At the DICOM layer the traffic is not anonymous. A C-STORE sub-operation can carry Move Originator Application Entity Title (0000,1030) and Move Originator Message ID (0000,1031), naming the AE that invoked the C-MOVE and the request it belongs to. A firewall sees none of that: it sees an inbound connection from the archive with no outbound request of its own to match it against.
Inside one subnet that rule is cheap. Across an organizational boundary it is a standing exception someone has to configure, document, and maintain. A teleradiology partner, a research archive, or a second site is exactly where that exception is hardest to get approved, because it means punching a hole for traffic nobody on that side initiated.
The AE Title Has to Exist Before the Request Does
Move Destination isn’t a free-text address. It’s an AE title the archive has to already recognize, mapped to a specific IP and port in its own configuration, the same discipline PACS integration demands of a modality-to-PACS association. The standard also requires that AE be capable of serving as a Storage SCP, which is the listener requirement again, stated as a precondition on the request.
If that entry doesn’t exist yet, the C-MOVE fails outright, and the standard has a named status code for exactly this case: “Refused: Move Destination unknown”, status A801. No connection ever gets attempted. That is a cleaner failure than one that gets attempted and silently rejected downstream. It still means a new destination is a configuration change on the archive, not something a requester can name on the fly.
Sub-Operation Status and Partial Failures
A single C-MOVE request can cover an entire study, which might mean dozens or hundreds of individual C-STORE sub-operations firing one after another to the destination. The standard has the archive report on that progress as it happens: a Pending response carries the Number of Remaining, Completed, Failed, and Warning sub-operations, updated as the transfer runs.
The final response is where partial failure shows up, and it’s easy to miss if a system only checks for outright failure. If every image made it, the archive returns Success. If every sub-operation failed, which is what a blocked destination produces, the status is Failure. If some made it and some didn’t, the status is Warning, “Sub-operations Complete – One or more Failures”, and the response carries a Failed SOP Instance UID List naming exactly which instances didn’t make it.
A monitoring process that only alerts on Failure will let a Warning through as if the transfer fully succeeded, when the destination might be missing several images out of a hundred-image series. Reconciling that list against what the destination actually received is the only way to know for certain a study arrived whole.
When C-GET Is the Better Answer
C-GET solves the exact problem C-MOVE creates, by removing the second association. The standard’s language is the mirror image of C-MOVE’s: the C-STORE sub-operations “shall be accomplished on the same Association as the C-GET operation”. A note makes the contrast explicit: “The application entity that receives the stored SOP Instances is always the originator of the C-GET operation.”
There’s no Move Destination to configure, because there’s nothing to configure. The requester already has an open connection to the archive, and the images come back on it. That closes the firewall problem entirely; nothing unsolicited ever arrives anywhere.
It does ask more of the archive on the other end. Support for C-GET has to be negotiated separately at association time, same as C-MOVE. An archive taking on the SCP role for C-GET has to run the SCU side of Storage over a connection it didn’t open, layered inside a request it’s still answering.
Plenty of PACS implementations built their retrieval workflow around C-MOVE first, because it is the operation that can put a study somewhere other than the requester. Fan-out is not one request, though: Move Destination names a single receiving AE, so three partners means three C-MOVE requests. What C-MOVE buys is that the requester never relays the pixels itself. C-GET has no equivalent, because the requester is always the receiver.
The two aren’t interchangeable. C-MOVE is the right tool when a study genuinely needs to land somewhere other than the requester. C-GET is the right tool when the requester wants the study for itself and would rather not manage a destination AE, a firewall exception, and a separate connection just to get it.
How DICOMweb’s WADO-RS Changes the Picture
DICOMweb sidesteps the whole inbound-association question by not using DIMSE associations at all. The standard defines it as web services “using the HTTP family of protocols”, built to manage and distribute DICOM information objects, with the RESTful services themselves designated DICOMweb. The Retrieve Transaction inside it, commonly called WADO-RS, pulls a study, series, or instance with an ordinary HTTP GET request against a URL like /studies/{study}. That is the same request pattern a browser uses to load any other resource.
That single detail removes everything C-MOVE requires. There’s no Move Destination, because the response comes back on the same HTTP connection the client opened. There’s no unsolicited inbound connection for a firewall to have to permit, because the traffic looks exactly like any other outbound web request.
For the retrieval mechanics alone, WADO-RS sits closer to C-GET than to C-MOVE: requester and destination are always the same party. The difference is the infrastructure, a single outbound HTTPS port every network team already knows how to open, instead of a DICOM-specific association nobody outside imaging has configured before.
What This Means for an Integrator
The questions worth asking before building against any Query/Retrieve implementation follow directly from where C-MOVE actually breaks. Does the archive support C-GET or DICOMweb retrieval as an alternative, for cases where a client wants a study for itself rather than routing it onward? Is the destination AE title already registered on the archive, with a matching IP and port, before the first request is ever sent?
Is the firewall exception for an inbound C-STORE connection documented somewhere a network team can find it during an incident, rather than tribal knowledge from whoever set it up? And does the integration read the Failed SOP Instance UID List, or does it treat a Warning response as a clean transfer?
EBM mAIn PACS® publishes its DICOM services directly rather than leaving them as a general claim: native DICOM C-STORE, Query/Retrieve, Modality Worklist, and Storage Commitment are listed on its own integrations page. Which specific DIMSE-C services and roles a Query/Retrieve implementation supports, C-MOVE as an SCP, C-GET, or both, is what a conformance statement exists to spell out. Asking for it, and testing a real transfer against it, is what turns “supports Query/Retrieve” from a marketing line into something a partner can build a retrieval workflow on.
Where This Fits With the Rest of the Stack
C-MOVE is one piece of a bigger retrieval picture. The same store-and-forward pattern, an archive acting as Storage SCU against a destination that has to be listening, runs continuously underneath DICOM routers. It runs again under teleradiology distribution, where the destination is a remote reader rather than another archive.
C-MOVE, C-GET and WADO-RS answer the same two questions differently. The first is who actually receives the study. The second is whether the network path between the archive and that destination already exists, or is something an integration has to build before the first study ever moves.
