<!-- llms-explorer concept facts · https://llms-explorer.com/tree/pinned-stopsharddraining-command-forwarding-and-catalog-mutation-boundaries/ · pack 2026-11-02 · ~3005 tokens -->

# Pinned stopShardDraining command forwarding and catalog mutation boundaries

> Source-anchored research for Pinned stopShardDraining command forwarding and catalog mutation boundaries. Run status: COMPLETED.

Parent: [Shard draining cancellation, status and commit protocol](https://llms-explorer.com/tree/shard-draining-cancellation-status-and-commit-protocol/) · 4 facets · 14 facts · page: https://llms-explorer.com/tree/pinned-stopsharddraining-command-forwarding-and-catalog-mutation-boundaries/

## Structure and components

- The draining branch first calls logChangeChecked with label "removeShard.stopShardDraining", an empty namespace, the shard name, and writeConcernLocalHavingUpstreamWaiter. It then updates the matching shard document in NamespaceString::kConfigsvrShardsNamespace using $unset on ShardType::draining, passes false for upsert, and again uses writeConcernLocalHavingUpstreamWaiter. The checked changelog call precedes the checked update; the complete stopDrain body contains no explicit transaction wrapper around those calls. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/global_catalog/sharding_catalog_client.h)

## How it works

- At entry, stopDrain invokes resetDDLBlockingForTopologyChangeIfNeeded. The recovery helper reads the server-configuration recovery document identified by kAddOrRemoveShardInProgressRecoveryDocumentId, returns when it is empty, and otherwise calls unblockDDLCoordinators. The latter sets the add/remove-shard-in-progress cluster parameter to false unless its skip-blocking failpoint returns early; its recovery-document deletion branch is conditional on removeRecoveryDocument. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/topology_change_helpers.cpp)
- The recovery-reset call is conditional on persisted recovery state: resetDDLBlockingForTopologyChangeIfNeeded looks for kAddOrRemoveShardInProgressRecoveryDocumentId in NamespaceString::kServerConfigurationNamespace, returns immediately when absent, and otherwise calls unblockDDLCoordinators. This is the helper that stopDrain invokes before taking its cardinality and membership locks. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/topology_change_helpers.cpp)

## Problems, failure modes and limitations

- Before calling topology_change_helpers::stopShardDraining, the config-server handler resolves the request parameter through resolveShardId with allowNonShardIdIdentifiers=true. The resolver calls getShard, returns a non-OK status unchanged, or returns the resulting shard's ID. The internal request IDL declares isTransitionToDedicatedCS as optionalBool; the handler uses false when that flag is absent. Its IllegalOperation guard permits ShardId::kConfigServerId only when that flag is true; the error directs callers to the dedicated-config-server transition stop command. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/configsvr_stop_shard_draining_command.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/shard_registry.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/remove_shard.idl)

## Facts and statements

- The router constructs ConfigSvrStopShardDraining from the command target, copies RemoveShardRequestBase and the database name, and sends the filtered BSON command to the config shard on the admin database with primary-only read preference, appendMajorityWriteConcern using the operation context write concern, and the idempotent retry policy. It checks the effective command response status. The config-server invocation explicitly requires majority write concern. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/cluster_stop_shard_draining_cmd.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/configsvr_stop_shard_draining_command.cpp)
- The internal config-server handler calls setAlwaysInterruptAtStepDownOrUp_UNSAFE on its operation context, checks the config-server role and majority write concern, and changes the operation read concern to local for config-database reads. Its block-exit handler sets the client last-op time to the system last-op time and catches interruption errors from that step. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/configsvr_stop_shard_draining_command.cpp)
- The config-server invocation calls topology_change_helpers::stopShardDraining. That helper holds a ScopedCollectionDDLLock for NamespaceString::kConfigsvrShardsNamespace with reason "stopShardDraining" and MODE_X while it calls ShardingCatalogManager::stopDrain. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/configsvr_stop_shard_draining_command.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/remove_shard_command_helpers.cpp)
- Inside the helper-held exclusive DDL lock, stopDrain first calls resetDDLBlockingForTopologyChangeIfNeeded. It then acquires the cluster-cardinality-parameter lock followed by the shard-membership lock, both as exclusive locks. The source comment states that these locks prevent add/remove-shard operations and their cardinality-parameter update from interleaving with stopping drain. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/remove_shard_command_helpers.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp)
- After locking, stopDrain reads the shard through getShardIfExists and asserts that it exists, then checks isShardCurrentlyDraining. Only the true branch records removeShard.stopShardDraining in the changelog and updates the shard catalog document. Thus an existing shard that is already not draining skips both those writes in this function, although the earlier recovery-reset call has already occurred. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/topology_change_helpers.cpp)
- The retained tracker snapshot names SERVER-107536 in its Core Server heading. Its description requests changing the changelog label from "removeShard.stopShardDraining" to "stopShardDraining". The pinned stopDrain body still passes "removeShard.stopShardDraining" to logChangeChecked. This pairs an identified tracker request with the literal observed in the implementation; the request does not establish that this revision implemented the replacement. (high confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://jira.mongodb.org/browse/SERVER-107536)
- Boundary inference from the inspected path: the router/config-server handoff, exclusive-lock helper, and stopDrain body establish command forwarding and guarded catalog mutation, while the optional recovery branch resets DDL blocking. These source spans do not establish an interruption guarantee for an already-running remote migration. The remote migration outcome remains outside what these source spans establish. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/cluster_stop_shard_draining_cmd.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/configsvr_stop_shard_draining_command.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/remove_shard_command_helpers.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/topology_change_helpers.cpp)
- The source declares skipBlockingDDLCoordinatorsDuringAddAndRemoveShard with MONGO_FAIL_POINT_DEFINE. In unblockDDLCoordinators, the corresponding failpoint check can return early. Otherwise the function calls setAddOrRemoveShardInProgressClusterParam with false before its conditional recovery-document deletion branch. The declaration defaults removeRecoveryDocument to true, and resetDDLBlockingForTopologyChangeIfNeeded calls the helper without an explicit second argument. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/topology_change_helpers.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/topology_change_helpers.h)
- For a draining shard, stopDrain logs removeShard.stopShardDraining before updating NamespaceString::kConfigsvrShardsNamespace. The update selects ShardType::name() equal to the shard name, uses $unset on ShardType::draining, and passes false for upsert. Both the changelog and catalog update use writeConcernLocalHavingUpstreamWaiter; the outer config-server command separately requires majority write concern and installs the system-last-op block-exit handler. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/configsvr_stop_shard_draining_command.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/global_catalog/sharding_catalog_client.h)
- Source-boundary observation: the inspected stopShardDraining helper directly calls stopDrain under the DDL lock, and the complete stopDrain body performs recovery reset, locking, existence/draining checks, changelog recording and a draining-field unset. Neither body explicitly issues a remote migration-cancel request or waits for a remote migration to acknowledge interruption. These source observations do not establish an already-running remote migration interruption guarantee. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/remove_shard_command_helpers.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/603d1d985b3e38b968a9c71753af223440a3565f/src/mongo/db/topology/sharding_catalog_manager_shard_operations.cpp)
