Ripple in a SciPy Butterworth SOS Filter
I can find 2 errors at a quick glance :
1 - You should discard the transient when measuring the steady-state gain at for a given frequency $f$. I haven't checked how long the transient last, but you should factor it in your RMS measurement.
2 - The RMS calculation only works when the number of samples corresponds to a whole number of periods. Otherwise, the calculation is biased.
Edit :
Period in this context means the signal period. As you are in the discrete domain, this is the ratio between the sampling frequency and the signal frequency
$T = \frac{f_s}{f}$
For transient, see this site
https://www.dsprelated.com/freebooks/filters/Transient_Response_Steady_State.html
Edit 2 :
Assuming your signal frequency is 1 kHz
$T = \frac{44.1 kHz}{1 kHz} = 44.1$
Since you have 44.1 samples per period, the RMS calculation with only 44 samples will have some bias. However, if you use 441 samples, you will have exactly 10 signal periods and then the RMS calculation will have no bias.
As for the transient, you should plot the time response. You should be able to evaluate how long the transient lasts.