There is the "single source of truth" problem where you need to compute something exactly the same way at all points in the software that need to compute that thing. In these cases you really want a single library implementation so that the meaning of that computation does not accidentally diverge over time since there is a single implementation to maintain.
There is the "reuse behaviors in unrelated contexts" problem where you want to create implementations of common useful behaviors that can be abstracted over many use cases, often in the context of data structures and algorithms. In these cases you really want generics and metaprogramming to codegen a context-specific implementation rather than sharing a single implementation with a spaghetti mess of conditionals.
DRY works best when it fits neatly and exclusively into one of these two categories. Cases that fit in neither category, such as the practice of decomposing every non-trivial function into a bunch of micro-functions that call each other, are virtually always a maintenance nightmare for no obvious benefit. Cases that fit into both categories, such as expansive metaprogramming libraries, become difficult to maintain by virtue of the combinatorial explosion of possible implementations that might be generated across the allowable parameter space -- the cognitive overhead grows exponentially for what is often a linear increase in value.