diff --git a/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx b/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx
index b4664feb121d277d1586c7eaefc09e1d5bf6bbbc..3c07f5f73d6eaa9f0771091225d4aa66315a3601 100644
--- a/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx
+++ b/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx
@@ -71,7 +71,7 @@ public:
    void InitSlot(TTreeReader *, unsigned int) {}
    void Exec(unsigned int slot);
    void Finalize();
-   ULong64_t *PartialUpdate(unsigned int slot);
+   ULong64_t &PartialUpdate(unsigned int slot);
 };
 
 class FillHelper {
@@ -126,7 +126,7 @@ public:
       }
    }
 
-   Hist_t *PartialUpdate(unsigned int);
+   Hist_t &PartialUpdate(unsigned int);
 
    void Finalize();
 };
@@ -245,7 +245,7 @@ public:
    }
    void Finalize() { fTo->Merge(); }
 
-   HIST *PartialUpdate(unsigned int slot) { return fTo->GetAtSlotRaw(slot); }
+   HIST &PartialUpdate(unsigned int slot) { return *fTo->GetAtSlotRaw(slot); }
 };
 
 // IMPORTANT NOTE: changes to this class should probably be replicated in its partial specialization below
@@ -278,7 +278,7 @@ public:
       }
    }
 
-   COLL *PartialUpdate(unsigned int slot) { return fColls[slot].get(); }
+   COLL &PartialUpdate(unsigned int slot) { return fColls[slot].get(); }
 };
 
 // note: changes to this class should probably be replicated in its unspecialized
@@ -317,7 +317,7 @@ public:
       }
    }
 
-   std::vector<T> *PartialUpdate(unsigned int slot) { return fColls[slot].get(); }
+   std::vector<T> &PartialUpdate(unsigned int slot) { return *fColls[slot]; }
 };
 
 template <typename F, typename T>
@@ -344,7 +344,7 @@ public:
       for (auto &t : fReduceObjs) *fReduceRes = fReduceFun(*fReduceRes, t);
    }
 
-   T *PartialUpdate(unsigned int slot) { return &fReduceObjs[slot]; }
+   T &PartialUpdate(unsigned int slot) { return fReduceObjs[slot]; }
 };
 
 class MinHelper {
@@ -367,7 +367,7 @@ public:
 
    void Finalize();
 
-   double *PartialUpdate(unsigned int slot) { return &fMins[slot]; }
+   double &PartialUpdate(unsigned int slot) { return fMins[slot]; }
 };
 
 extern template void MinHelper::Exec(unsigned int, const std::vector<float> &);
@@ -395,7 +395,7 @@ public:
 
    void Finalize();
 
-   double *PartialUpdate(unsigned int slot) { return &fMaxs[slot]; }
+   double &PartialUpdate(unsigned int slot) { return fMaxs[slot]; }
 };
 
 extern template void MaxHelper::Exec(unsigned int, const std::vector<float> &);
@@ -428,7 +428,7 @@ public:
 
    void Finalize();
 
-   double *PartialUpdate(unsigned int slot);
+   double &PartialUpdate(unsigned int slot);
 };
 
 extern template void MeanHelper::Exec(unsigned int, const std::vector<float> &);
diff --git a/tree/treeplayer/inc/ROOT/TDFNodes.hxx b/tree/treeplayer/inc/ROOT/TDFNodes.hxx
index edc97f8a537404bcb0ae75dc66bb5f42ac1e9766..c1adffd8cc307605b82b04f9b17e7904165a1dd2 100644
--- a/tree/treeplayer/inc/ROOT/TDFNodes.hxx
+++ b/tree/treeplayer/inc/ROOT/TDFNodes.hxx
@@ -407,9 +407,9 @@ private:
    // this overload is SFINAE'd out if Helper does not implement `PartialUpdate`
    // the template parameter is required to defer instantiation of the method to SFINAE time
    template <typename H = Helper>
-   auto PartialUpdateImpl(unsigned int slot) -> decltype(std::declval<H>().PartialUpdate(slot))
+   auto PartialUpdateImpl(unsigned int slot) -> decltype(std::declval<H>().PartialUpdate(slot), (void *)(nullptr))
    {
-      return fHelper.PartialUpdate(slot);
+      return &fHelper.PartialUpdate(slot);
    }
    // this one is always available but has lower precedence thanks to `...`
    void *PartialUpdateImpl(...) {
diff --git a/tree/treeplayer/src/TDFActionHelpers.cxx b/tree/treeplayer/src/TDFActionHelpers.cxx
index b742244f2261ac6ed01b97006e7846576e900e5c..bc6af2326b94fe2013ef77b328d8083d9eedc559 100644
--- a/tree/treeplayer/src/TDFActionHelpers.cxx
+++ b/tree/treeplayer/src/TDFActionHelpers.cxx
@@ -32,9 +32,9 @@ void CountHelper::Finalize()
    }
 }
 
-ULong64_t *CountHelper::PartialUpdate(unsigned int slot)
+ULong64_t &CountHelper::PartialUpdate(unsigned int slot)
 {
-   return &fCounts[slot];
+   return fCounts[slot];
 }
 
 void FillHelper::UpdateMinMax(unsigned int slot, double v)
@@ -72,7 +72,7 @@ void FillHelper::Exec(unsigned int slot, double v, double w)
    fWBuffers[slot].emplace_back(w);
 }
 
-Hist_t *FillHelper::PartialUpdate(unsigned int slot)
+Hist_t &FillHelper::PartialUpdate(unsigned int slot)
 {
    auto &partialHist = fPartialHists[slot];
    // TODO it is inefficient to re-create the partial histogram everytime the callback is called
@@ -80,7 +80,7 @@ Hist_t *FillHelper::PartialUpdate(unsigned int slot)
    partialHist.reset(new Hist_t(*fResultHist));
    auto weights = fWBuffers[slot].empty() ? nullptr : fWBuffers[slot].data();
    partialHist->FillN(fBuffers[slot].size(), fBuffers[slot].data(), weights);
-   return partialHist.get();
+   return *partialHist;
 }
 
 void FillHelper::Finalize()
@@ -182,10 +182,10 @@ void MeanHelper::Finalize()
    *fResultMean = sumOfSums / (sumOfCounts > 0 ? sumOfCounts : 1);
 }
 
-double *MeanHelper::PartialUpdate(unsigned int slot)
+double &MeanHelper::PartialUpdate(unsigned int slot)
 {
    fPartialMeans[slot] = fSums[slot] / fCounts[slot];
-   return &fPartialMeans[slot];
+   return fPartialMeans[slot];
 }
 
 template void MeanHelper::Exec(unsigned int, const std::vector<float> &);