diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,19 @@
 # Changelog for srtree
 
+## 3.0.0.5
+
+- **Fix NLopt re-entered thousands of times per fit** (`NonlinearOpt` + `SearchSR`):
+  - `minimizeNLLWith` no longer `{-# INLINE #-}` and forces the NLopt result
+    once (`t_opt `seq` nEvs `seq` ...`), so the optimization is not re-run at
+    every use site. Previously GHC duplicated the lazy `where` thunk, re-entering
+    NLopt ~tens of thousands of times for a single fit of expressions with a
+    parameter in a division/log denominator (e.g. `t1/(x0+t1)`).
+  - `fitnessFun` now `DeepSeq.force`s the `minimizeNLL'` result, so the parallel
+    fit's forcing of both the fitness and the theta does not re-trigger the
+    unshared optimization.
+  - Effect: previously-hanging eggp fits (e.g. `gen=6, nPop=30`) now complete in
+    ~1-9 s.
+
 ## 3.0.0.4
 
 - **Export `createLoss`**: expose compiled loss function for external use
diff --git a/src/Algorithm/EqSat/SearchSR.hs b/src/Algorithm/EqSat/SearchSR.hs
--- a/src/Algorithm/EqSat/SearchSR.hs
+++ b/src/Algorithm/EqSat/SearchSR.hs
@@ -122,7 +122,10 @@
     else (val, theta)
   where
     nParams       = countParamsUniq tree + if loss == NLL ROXY then 3 else if loss == NLL Gaussian then 1 else 0
-    (theta, lossVal, _) = minimizeNLL' VAR1 backend loss mYErr nIter x y tree thetaOrig
+    -- force the NLopt result once so the parallel fit's `DeepSeq.force` of both
+    -- the fitness and the theta never re-runs the optimization (which otherwise
+    -- re-entered NLopt thousands of times for degenerate expressions).
+    (theta, lossVal, _) = DeepSeq.force (minimizeNLL' VAR1 backend loss mYErr nIter x y tree thetaOrig)
     evalF a b c   = negate $ compileLoss a (buildLoss loss (fromIntegral (V.length b)) tree) b c $ if nParams == 0 then thetaOrig else theta
     -- at folds=1 the validation split is the training data itself, so the
     -- train loss returned by minimizeNLL' already is the val loss; skipping
diff --git a/src/Algorithm/SRTree/NonlinearOpt.hs b/src/Algorithm/SRTree/NonlinearOpt.hs
--- a/src/Algorithm/SRTree/NonlinearOpt.hs
+++ b/src/Algorithm/SRTree/NonlinearOpt.hs
@@ -41,7 +41,11 @@
 minimizeNLLWith funAndGrad alg niter t0
   | niter == 0 = (t0, f, 0)
   | n == 0     = (t0, f, 0)
-  | otherwise  = (t_opt', fst (funAndGrad t_opt), nEvs)
+  | otherwise  = let (t_opt, nEvs) = case minimizeLocal problem t0' of
+                                        Right sol -> (solutionParams sol, nEvals sol)
+                                        Left e    -> (t0', 0)
+                     t_opt'        = G.convert t_opt
+                 in t_opt `seq` nEvs `seq` (t_opt', fst (funAndGrad t_opt), nEvs)
   where
     t0'        = G.convert t0
     n          = V.length t0
@@ -51,11 +55,8 @@
     algorithm  = alg funAndGrad (Just $ VectorStorage $ fromIntegral n)
     stop       = ObjectiveRelativeTolerance 1e-6 :| [ObjectiveAbsoluteTolerance 1e-6, MaximumEvaluations (fromIntegral niter)]
     problem    = LocalProblem (fromIntegral n) stop algorithm
-    (t_opt, nEvs) = case minimizeLocal problem t0' of
-                      Right sol -> (solutionParams sol, nEvals sol)
-                      Left e    -> (t0', 0)
-    t_opt'      = G.convert t_opt
-{-# INLINE minimizeNLLWith #-}
+-- no INLINE: inlining duplicated the lazy `where` thunk so the NLopt call was
+-- re-evaluated thousands of times per fit.
 
 -- | Compile the loss function and gradient for a tree, returning a reusable
 -- closure. Use this when you need to optimize the same expression with
diff --git a/srtree.cabal b/srtree.cabal
--- a/srtree.cabal
+++ b/srtree.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:               srtree
-version:            3.0.0.4
+version:            3.0.0.5
 synopsis:           A general library to work with Symbolic Regression expression trees.
 description:        A Symbolic Regression Tree data structure to work with mathematical expressions with support to first order derivative and simplification;
 license:            BSD3
