diff --git a/actions/ost-compare-structures b/actions/ost-compare-structures
index 86ab664e96a2d98a31ac4f4679cd486bec3f3288..30a14717c99e70b66e3332869a8e66ffcea9f8d1 100644
--- a/actions/ost-compare-structures
+++ b/actions/ost-compare-structures
@@ -251,6 +251,19 @@ def _ParseArgs():
         action="store_true",
         help=("Make alignment based on residue number instead of using\n"
               "a global BLOSUM62-based alignment."))
+    parser.add_argument(
+        "--qs-max-mappings-extensive",
+        dest="qs_max_mappings_extensive",
+        type=int,
+        default=1000000,
+        help=("Maximal number of chain mappings to test for 'extensive'\n"
+              "chain mapping scheme which is used as a last resort if\n"
+              "other schemes failed. The extensive chain mapping search\n"
+              "must in the worst case check O(N!) possible mappings for\n"
+              "complexes with N chains. Two octamers without symmetry\n"
+              "would require 322560 mappings to be checked. To limit\n"
+              "computations, no scores are computed if we try more than\n"
+              "the maximal number of chain mappings."))
     #
     # lDDT options
     #
@@ -683,13 +696,19 @@ def _Main():
             qs_scorer = qsscoring.QSscorer(reference,
                                            model,
                                            opts.residue_number_alignment)
+            qs_scorer.max_mappings_extensive = opts.qs_max_mappings_extensive
             if opts.chain_mapping is not None:
                 ost.LogInfo(
                     "Using custom chain mapping: %s" % str(
                         opts.chain_mapping))
                 qs_scorer.chain_mapping = opts.chain_mapping
             else:
-                qs_scorer.chain_mapping  # just to initialize it
+                try:
+                  qs_scorer.chain_mapping  # just to initialize it
+                except qsscoring.QSscoreError as ex:
+                  ost.LogError('Chain mapping failed:', str(ex))
+                  ost.LogError('Skipping comparison')
+                  continue
             ost.LogInfo("-" * 80)
             ost.LogInfo("Checking consistency between %s and %s" % (
                         model_name, reference_name))
diff --git a/modules/doc/actions.rst b/modules/doc/actions.rst
index 8c31b7d4108e670f8c6091059438f82e4a8bb5e9..20858ec9b306e5ef9bbd3025b80ad4c23cbe46d4 100644
--- a/modules/doc/actions.rst
+++ b/modules/doc/actions.rst
@@ -24,7 +24,9 @@ lDDT scores between two complexes from the command line with:
                            [-rs REFERENCE_SELECTION] [-ms MODEL_SELECTION]
                            [-ca] [-ft] [-cl COMPOUND_LIBRARY] [-qs]
                            [-c CHAIN_MAPPING [CHAIN_MAPPING ...]]
-                           [--qs-rmsd] [-rna] [-l] [-ir INCLUSION_RADIUS]
+                           [--qs-rmsd] [-rna]
+                           [--qs-max-mappings-extensive QS_MAX_MAPPINGS_EXTENSIVE]
+                           [-l] [-ir INCLUSION_RADIUS]
                            [-ss SEQUENCE_SEPARATION] [-spr] [-ml]
                            [-rm REMOVE [REMOVE ...]] [-ce] [-mn] [-sc]
                            [-p PARAMETER_FILE] [-bt BOND_TOLERANCE]
diff --git a/modules/mol/alg/pymod/qsscoring.py b/modules/mol/alg/pymod/qsscoring.py
index 8339bf2fa966f29437d03331f1840adb8dd70df0..0e584fe7f988013687eb4fe1e31e1422f2a02d0b 100644
--- a/modules/mol/alg/pymod/qsscoring.py
+++ b/modules/mol/alg/pymod/qsscoring.py
@@ -143,6 +143,19 @@ class QSscorer:
 
     :type: :class:`int`
 
+  .. attribute:: max_mappings_extensive
+
+    Maximal number of chain mappings to test for 'extensive'
+    :attr:`chain_mapping_scheme`. The extensive chain mapping search must in the
+    worst case check O(N^2) * O(N!) possible mappings for complexes with N
+    chains. Two octamers without symmetry would require 322560 mappings to be
+    checked. To limit computations, a :class:`QSscoreError` is thrown if we try
+    more than the maximal number of chain mappings.
+    The value must be set before the first use of :attr:`chain_mapping`.
+    By default it is set to 100000.
+
+    :type: :class:`int`
+
   .. attribute:: res_num_alignment
 
     Forces each alignment in :attr:`alignments` to be based on residue numbers
@@ -174,6 +187,7 @@ class QSscorer:
     self.res_num_alignment = res_num_alignment
     self.calpha_only = self.qs_ent_1.calpha_only or self.qs_ent_2.calpha_only
     self.max_ca_per_chain_for_cm = 100
+    self.max_mappings_extensive = 100000
     # init cached stuff
     self._chem_mapping = None
     self._ent_to_cm_1 = None
@@ -361,12 +375,13 @@ class QSscorer:
     :type: :class:`dict` with key / value = :class:`str` (chain names, key
            for :attr:`ent_to_cm_1`, value for :attr:`ent_to_cm_2`)
     :raises: :class:`QSscoreError` if there are too many combinations to check
-             to find a chain mapping.
+             to find a chain mapping (see :attr:`max_mappings_extensive`).
     """
     if self._chain_mapping is None:
       self._chain_mapping, self._chain_mapping_scheme = \
         _GetChainMapping(self.ent_to_cm_1, self.ent_to_cm_2, self.symm_1,
-                         self.symm_2, self.chem_mapping)
+                         self.symm_2, self.chem_mapping,
+                         self.max_mappings_extensive)
       LogInfo('Mapping found: %s' % str(self._chain_mapping))
     return self._chain_mapping
 
@@ -1811,7 +1826,8 @@ def _FindSymmetry(qs_ent_1, qs_ent_2, ent_to_cm_1, ent_to_cm_2, chem_mapping):
   return [], []
 
 
-def _GetChainMapping(ent_1, ent_2, symm_1, symm_2, chem_mapping):
+def _GetChainMapping(ent_1, ent_2, symm_1, symm_2, chem_mapping,
+                     max_mappings_extensive):
   """
   :return: Tuple with mapping from *ent_1* to *ent_2* (see
            :attr:`QSscorer.chain_mapping`) and scheme used (see
@@ -1822,6 +1838,7 @@ def _GetChainMapping(ent_1, ent_2, symm_1, symm_2, chem_mapping):
   :param symm_1: See :attr:`QSscorer.symm_1`
   :param symm_2: See :attr:`QSscorer.symm_2`
   :param chem_mapping: See :attr:`QSscorer.chem_mapping`
+  :param max_mappings_extensive: See :attr:`QSscorer.max_mappings_extensive`
   """
   LogInfo('Symmetry-groups used in %s: %s' % (ent_1.GetName(), str(symm_1)))
   LogInfo('Symmetry-groups used in %s: %s' % (ent_2.GetName(), str(symm_2)))
@@ -1861,8 +1878,8 @@ def _GetChainMapping(ent_1, ent_2, symm_1, symm_2, chem_mapping):
   LogInfo('Inter Symmetry-group mappings to check: %s' \
           % count['inter']['mappings'])
   nr_mapp = count['intra']['mappings'] + count['inter']['mappings']
-  # if nr_mapp > 100000: # 322560 is octamer vs octamer
-  #   raise QSscoreError('Too many possible mappings: %s' % nr_mapp)
+  if nr_mapp > max_mappings_extensive:
+    raise QSscoreError('Too many possible mappings: %s' % nr_mapp)
 
   # to speed up the computations we cache chain views and RMSDs
   cached_rmsd = _CachedRMSD(ent_1, ent_2)