diff --git a/Framework/API/src/WorkspaceFactory.cpp b/Framework/API/src/WorkspaceFactory.cpp
index 30dedbc1fe13fbb5d4707218919d8824470e3bbd..bc8b78456c8f83a02e5d0dc056e1052220827107 100644
--- a/Framework/API/src/WorkspaceFactory.cpp
+++ b/Framework/API/src/WorkspaceFactory.cpp
@@ -5,6 +5,7 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidAPI/WorkspaceFactory.h"
+#include "MantidAPI/BinEdgeAxis.h"
 #include "MantidAPI/IPeaksWorkspace.h"
 #include "MantidAPI/ITableWorkspace.h"
 #include "MantidAPI/MatrixWorkspace.h"
@@ -127,21 +128,26 @@ void WorkspaceFactoryImpl::initializeFromParent(
 
   // deal with axis
   for (size_t i = 0; i < parent.m_axes.size(); ++i) {
-    const size_t newAxisLength = child.getAxis(i)->length();
-    const size_t oldAxisLength = parent.getAxis(i)->length();
-
-    if (!differentSize || newAxisLength == oldAxisLength) {
-      // Need to delete the existing axis created in init above
-      delete child.m_axes[i];
+    if (parent.m_axes[i]->isSpectra()) {
+      // By default the child already has a spectra axis which
+      // does not need to get cloned from the parent.
+      continue;
+    }
+    const bool isBinEdge =
+        dynamic_cast<const BinEdgeAxis *const>(parent.m_axes[i]) != nullptr;
+    const size_t newAxisLength =
+        child.m_axes[i]->length() + (isBinEdge ? 1 : 0);
+    const size_t oldAxisLength = parent.m_axes[i]->length();
+
+    // Need to delete the existing axis created in init above
+    delete child.m_axes[i];
+    child.m_axes[i] = nullptr;
+    if (newAxisLength == oldAxisLength) {
       // Now set to a copy of the parent workspace's axis
       child.m_axes[i] = parent.m_axes[i]->clone(&child);
     } else {
-      if (!parent.getAxis(i)->isSpectra()) // WHY???
-      {
-        delete child.m_axes[i];
-        // Call the 'different length' clone variant
-        child.m_axes[i] = parent.m_axes[i]->clone(newAxisLength, &child);
-      }
+      // Call the 'different length' clone variant
+      child.m_axes[i] = parent.m_axes[i]->clone(newAxisLength, &child);
     }
   }
 }
diff --git a/Framework/Algorithms/src/ExtractSpectra2.cpp b/Framework/Algorithms/src/ExtractSpectra2.cpp
index c5b3dbfcabf98bf1fc4c1ca0a708aa45b92bbe65..3480c2ddc5214b269b11cc08d93a93e930f52ffb 100644
--- a/Framework/Algorithms/src/ExtractSpectra2.cpp
+++ b/Framework/Algorithms/src/ExtractSpectra2.cpp
@@ -6,6 +6,7 @@
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidAlgorithms/ExtractSpectra2.h"
 #include "MantidAPI/Algorithm.tcc"
+#include "MantidAPI/BinEdgeAxis.h"
 #include "MantidAPI/NumericAxis.h"
 #include "MantidAPI/TextAxis.h"
 #include "MantidDataObjects/EventWorkspace.h"
@@ -68,12 +69,15 @@ void ExtractSpectra2::exec() {
   Axis *inAxis1(nullptr);
   TextAxis *outTxtAxis(nullptr);
   NumericAxis *outNumAxis(nullptr);
+  bool isBinEdgeAxis(false);
   if (inputWS->axes() > 1) {
     inAxis1 = inputWS->getAxis(1);
     auto outAxis1 = outputWS->getAxis(1);
     outTxtAxis = dynamic_cast<TextAxis *>(outAxis1);
-    if (!outTxtAxis)
+    if (!outTxtAxis) {
       outNumAxis = dynamic_cast<NumericAxis *>(outAxis1);
+      isBinEdgeAxis = dynamic_cast<BinEdgeAxis *>(inAxis1) != nullptr;
+    }
   }
 
   Progress prog(this, 0.0, 1.0, indexSet.size());
@@ -96,6 +100,17 @@ void ExtractSpectra2::exec() {
     prog.report();
   }
 
+  if (isBinEdgeAxis) {
+    if (!indexSet.isContiguous()) {
+      throw std::invalid_argument("Cannot extract non-contiguous set of "
+                                  "spectra when the vertical axis has bin "
+                                  "edges.");
+    }
+    const auto outIndex = indexSet.size();
+    const auto inIndex = indexSet[indexSet.size() - 1] + 1;
+    outNumAxis->setValue(outIndex, inAxis1->operator()(inIndex));
+  }
+
   setProperty("OutputWorkspace", std::move(outputWS));
 }
 
diff --git a/Framework/Algorithms/test/ExtractFFTSpectrumTest.h b/Framework/Algorithms/test/ExtractFFTSpectrumTest.h
index a21bc0765b21cf739186bb1e9dddaaf2d2067b9d..66bdd6e3f52d989873d12543ae047035c38b6e71 100644
--- a/Framework/Algorithms/test/ExtractFFTSpectrumTest.h
+++ b/Framework/Algorithms/test/ExtractFFTSpectrumTest.h
@@ -87,7 +87,7 @@ public:
     TS_ASSERT_EQUALS(inputWS->blocksize(), outputWS->blocksize());
 
     // Units ( Axis 1 should be the same, Axis 0 should be "Time/ns"
-    TS_ASSERT_EQUALS(inputWS->getAxis(1)->unit(), outputWS->getAxis(1)->unit());
+    TS_ASSERT(*inputWS->getAxis(1)->unit() == *outputWS->getAxis(1)->unit());
     TS_ASSERT_EQUALS(outputWS->getAxis(0)->unit()->caption(), "Time");
     TS_ASSERT_EQUALS(outputWS->getAxis(0)->unit()->label(), "ns");
   }
diff --git a/Framework/Algorithms/test/ExtractSpectra2Test.h b/Framework/Algorithms/test/ExtractSpectra2Test.h
index 818c857e42a70e36a878b0431a391e83cc51bf1b..b8b05a3220598cd725efbba7fea3f3a9373ee3cd 100644
--- a/Framework/Algorithms/test/ExtractSpectra2Test.h
+++ b/Framework/Algorithms/test/ExtractSpectra2Test.h
@@ -10,6 +10,7 @@
 #include <cxxtest/TestSuite.h>
 
 #include "MantidAPI/AnalysisDataService.h"
+#include "MantidAPI/BinEdgeAxis.h"
 #include "MantidAlgorithms/ExtractSpectra2.h"
 #include "MantidDataObjects/Workspace2D.h"
 #include "MantidDataObjects/WorkspaceCreation.h"
@@ -125,6 +126,51 @@ public:
   }
 
   void test_parallel() { ParallelTestHelpers::runParallel(run_parallel); }
+
+  void test_BinEdgeAxis() {
+    auto input = createWorkspace();
+    BinEdgeAxis *axis = new BinEdgeAxis(input->getNumberHistograms() + 1);
+    for (size_t i = 0; i < axis->length(); ++i) {
+      axis->setValue(i, -2. + static_cast<double>(i));
+    }
+    input->replaceAxis(1, axis);
+    ExtractSpectra2 alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", std::move(input));
+    alg.setProperty("InputWorkspaceIndexSet", "1-3");
+    alg.setProperty("OutputWorkspace", "out");
+    alg.execute();
+    MatrixWorkspace_sptr out = alg.getProperty("OutputWorkspace");
+    auto outAxis = out->getAxis(1);
+    TS_ASSERT_DIFFERS(dynamic_cast<BinEdgeAxis *>(outAxis), nullptr)
+    TS_ASSERT_EQUALS(outAxis->length(), 4)
+    TS_ASSERT_EQUALS((*outAxis)(0), -1.)
+    TS_ASSERT_EQUALS((*outAxis)(1), 0.)
+    TS_ASSERT_EQUALS((*outAxis)(2), 1.)
+    TS_ASSERT_EQUALS((*outAxis)(3), 2.)
+  }
+
+  void test_BinEdgeAxis_fails_with_non_contiguous_indices() {
+    auto input = createWorkspace();
+    BinEdgeAxis *axis = new BinEdgeAxis(input->getNumberHistograms() + 1);
+    for (size_t i = 0; i < axis->length(); ++i) {
+      axis->setValue(i, -2. + static_cast<double>(i));
+    }
+    input->replaceAxis(1, axis);
+    ExtractSpectra2 alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", std::move(input));
+    alg.setProperty("InputWorkspaceIndexSet", "1,3");
+    alg.setProperty("OutputWorkspace", "out");
+    TS_ASSERT_THROWS_EQUALS(
+        alg.execute(), const std::invalid_argument &e, e.what(),
+        std::string("Cannot extract non-contiguous set of spectra when the "
+                    "vertical axis has bin edges."))
+  }
 };
 
 #endif /* MANTID_ALGORITHMS_EXTRACTSPECTRA2TEST_H_ */
diff --git a/Framework/DataHandling/test/CompressEventsTest.h b/Framework/DataHandling/test/CompressEventsTest.h
index f3a7b711f854c9333a988f70e36488ba037df57e..64c8568bfb1b09baf39cf1612b9474936a7c9d93 100644
--- a/Framework/DataHandling/test/CompressEventsTest.h
+++ b/Framework/DataHandling/test/CompressEventsTest.h
@@ -12,6 +12,7 @@
 #include "MantidAPI/Axis.h"
 #include "MantidDataHandling/CompressEvents.h"
 #include "MantidDataObjects/Workspace2D.h"
+#include "MantidKernel/Unit.h"
 #include "MantidTestHelpers/WorkspaceCreationHelper.h"
 
 using Mantid::MantidVecPtr;
@@ -113,8 +114,8 @@ public:
     TS_ASSERT_DELTA(output->readY(0)[1], 2.0, 1e-5);
     TS_ASSERT_DELTA(output->readE(0)[1], M_SQRT2, 1e-5);
     TS_ASSERT_EQUALS(output->YUnit(), input->YUnit());
-    TS_ASSERT_EQUALS(output->getAxis(0)->unit(), input->getAxis(0)->unit());
-    TS_ASSERT_EQUALS(output->getAxis(1)->unit(), input->getAxis(1)->unit());
+    TS_ASSERT(*output->getAxis(0)->unit() == *input->getAxis(0)->unit());
+    TS_ASSERT(*output->getAxis(1)->unit() == *input->getAxis(1)->unit());
   }
 
   // WEIGHTED_NOTIME tests
diff --git a/Framework/DataObjects/test/WorkspaceCreationTest.h b/Framework/DataObjects/test/WorkspaceCreationTest.h
index 82eee10415802f66fd473500d74251905831c32f..a7fe8b94993a82c5df0908200f969f18960ede5f 100644
--- a/Framework/DataObjects/test/WorkspaceCreationTest.h
+++ b/Framework/DataObjects/test/WorkspaceCreationTest.h
@@ -9,6 +9,7 @@
 
 #include <cxxtest/TestSuite.h>
 
+#include "MantidAPI/BinEdgeAxis.h"
 #include "MantidAPI/Run.h"
 #include "MantidDataObjects/EventWorkspace.h"
 #include "MantidDataObjects/SpecialWorkspace2D.h"
@@ -419,6 +420,30 @@ public:
     check_zeroed_data(*ws);
   }
 
+  void test_create_parent_numeric_vertical_axis() {
+    constexpr size_t parentNhist{3};
+    const auto parent = create<Workspace2D>(parentNhist, Histogram(Points{1}));
+    NumericAxis *parentAxis = new NumericAxis({-1.5, -0.5, 2.3});
+    parent->replaceAxis(1, parentAxis);
+    constexpr size_t nhist{2};
+    const auto ws = create<Workspace2D>(*parent, nhist, parent->histogram(0));
+    auto axis = ws->getAxis(1);
+    TS_ASSERT_DIFFERS(dynamic_cast<NumericAxis *>(axis), nullptr)
+    TS_ASSERT_EQUALS(axis->length(), nhist);
+  }
+
+  void test_create_parent_bin_edge_vertical_axis() {
+    constexpr size_t parentNhist{3};
+    const auto parent = create<Workspace2D>(parentNhist, Histogram(Points{1}));
+    BinEdgeAxis *parentAxis = new BinEdgeAxis({-1.5, -0.5, 2.3, 3.4});
+    parent->replaceAxis(1, parentAxis);
+    constexpr size_t nhist{2};
+    const auto ws = create<Workspace2D>(*parent, nhist, parent->histogram(0));
+    auto axis = ws->getAxis(1);
+    TS_ASSERT_DIFFERS(dynamic_cast<BinEdgeAxis *>(axis), nullptr)
+    TS_ASSERT_EQUALS(axis->length(), nhist + 1);
+  }
+
   void test_create_drop_events() {
     auto eventWS = create<EventWorkspace>(1, Histogram(BinEdges(3)));
     auto ws = create<HistoWorkspace>(*eventWS);
diff --git a/Framework/Indexing/inc/MantidIndexing/IndexSet.h b/Framework/Indexing/inc/MantidIndexing/IndexSet.h
index dfb3c25774aa69eeff63db6be74df21ebbca5295..ed50cbb1229484d106900bd8f78fb414a784ce2e 100644
--- a/Framework/Indexing/inc/MantidIndexing/IndexSet.h
+++ b/Framework/Indexing/inc/MantidIndexing/IndexSet.h
@@ -91,6 +91,8 @@ public:
     return m_indices[index];
   }
 
+  bool isContiguous() const noexcept;
+
 protected:
   ~IndexSet() = default;
 
@@ -139,6 +141,20 @@ IndexSet<T>::IndexSet(const std::vector<size_t> &indices, size_t fullRange)
   m_size = m_indices.size();
 }
 
+/**
+ * Check if the index range is contiguous and in ascending order.
+ */
+template <class T> bool IndexSet<T>::isContiguous() const noexcept {
+  if (!m_isRange || m_indices.size() > 1) {
+    for (size_t i = 0; i < m_indices.size() - 1; ++i) {
+      if (m_indices[i] + 1 != m_indices[i + 1]) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 } // namespace detail
 } // namespace Indexing
 } // namespace Mantid
diff --git a/Framework/Indexing/test/IndexSetTest.h b/Framework/Indexing/test/IndexSetTest.h
index 916f4429dd1990f9e9c9f9eccc7666c94cb2126b..7108f6770e5cbcda0bf5ca9ff08a792546440161 100644
--- a/Framework/Indexing/test/IndexSetTest.h
+++ b/Framework/Indexing/test/IndexSetTest.h
@@ -137,6 +137,17 @@ public:
     TS_ASSERT_THROWS_NOTHING(--it2);
     TS_ASSERT_EQUALS(*it2, 0);
   }
+
+  void test_isContiguous() {
+    const IndexSetTester empty{};
+    TS_ASSERT(empty.isContiguous())
+    const IndexSetTester range(3);
+    TS_ASSERT(range.isContiguous())
+    const IndexSetTester manualRange({3, 4, 5}, 6);
+    TS_ASSERT(manualRange.isContiguous())
+    IndexSetTester nonContiguous({2, 1, 3}, 4);
+    TS_ASSERT(!nonContiguous.isContiguous())
+  }
 };
 
 #endif /* MANTID_INDEXING_INDEXSETTEST_H_ */
diff --git a/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5
index 870024467e73790d3cf578ce13fa1e900a33ca4a..a9857f36b9e5022067e49ec3004d659683329c33 100644
--- a/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5
+++ b/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5
@@ -1 +1 @@
-d2185756bd31c3fce4bee9f4dc0bc441
+5019e21091a7b56a76b92b9f98cc59ec
diff --git a/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5
index 8bd1cff7ee995f771198fd4e5a5b861457a4292f..863af15f45b1492b2ffafa6f756b6fe7d7d0c84d 100644
--- a/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5
+++ b/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5
@@ -1 +1 @@
-a1a495cd3351cd56ed06c7c7844817bb
+c23e62c08f2ced8496ce229b071be418
diff --git a/docs/source/release/v3.14.0/framework.rst b/docs/source/release/v3.14.0/framework.rst
index 6fa2835b224cf9c32043fb620adc180b1c05fc12..cb09c9f08cd405141067812468a618e5bf6166ee 100644
--- a/docs/source/release/v3.14.0/framework.rst
+++ b/docs/source/release/v3.14.0/framework.rst
@@ -106,6 +106,7 @@ Bugfixes
 - `ConvertToMD <algm-ConvertToMD>` now uses the time-average value for logs when using them as ``OtherDimensions``
 - The input validator is fixed in :ref:`MostLikelyMean <algm-MostLikelyMean>` avoiding a segmentation fault.
 - Fixed a bug in `AlignAndFocusPowder <algm-AlignAndFocusPowder>` where a histogram input workspace did not clone propertly to the output workspace and properly masking a grouping workspace passed to `DiffractionFocussing <algm-DiffractionFocussing>`. Also adds initial unit tests for `AlignAndFocusPowder <algm-AlignAndFocusPowder>`.
+- Fixed a bug in :ref:`ExtractSpectra <algm-ExtractSpectra>` which was causing a wrong last value in the output's vertical axis if the axis type was ``BinEdgeAxis``.
 
 Python
 ------