Pandas version checks

  • [x] I have checked that this issue has not already been reported.

  • [x] I have confirmed this bug exists on the latest version of pandas.

  • [x] I have confirmed this bug exists on the main branch of pandas.

Reproducible Example

On pandas < 2.1 (e.g. 1.5.3, 2.0.3):


import pandas as pd
pd.Series(['a'], name='hi').to_pickle('G:/temp/test.pkl')

On pandas 2.3.0 and main:

import pandas as pd
ser = pd.read_pickle('G:/temp/test.pkl')        # appears to work
ser2 = pd.Series(['a'], name='hi')              # works
pd.testing.assert_series_equal(ser, ser2)       # works
pd.testing.assert_series_equal(ser, ser.copy()) # Attribute "name" are different

Issue Description

In doing a migration from 1.5.3 to the 2.x series we hit an issue where copying an unpickled Series drops its name (the actual operation was a .reindex_like, which called .copy under the hood). The bug begins with the pandas 2.1 series; I believe this may have been introduced in #51784 when the Series metadata was changed from name to _name.

Expected Behavior

It seems like an unpickled Series and its copy should be equal in all attributes, since that's what .copy does. However anything which does a copy (including implicit copies, such as calling .reindex()) currently causes the name to be dropped inadvertently.

Now I'm not sure to what extent read_pickle guarantees that all actions on an unpickled legacy object work the same way on a newly-created object. That said, one reason this may be worth fixing is that the problem seems to persist in new versions, i.e. rewriting the pickle with the new version directly doesn't mitigate the problem:

# using version 2.3.0
# read legacy pickle
ser = pd.read_pickle('G:/temp/test.pkl')
# write out new pickle of the object
ser.to_pickle('G:/temp/ser_copy.pkl')
# read in new pickle
ser_copy = pd.read_pickle('G:/temp/ser_copy.pkl')
pd.testing.assert_series_equal(ser, ser_copy)             # works
pd.testing.assert_series_equal(ser_copy, ser_copy.copy()) # fails, even though ser_copy is read in from a pickle created in 2.3.0)

And of course obviously calling ser.copy() to get a new pandas 2.3 object also does not work.

Thus it seems the only workaround to: 1) Read in the legacy pickle 2) Serialize the legacy pickle to some other format 3) Deserialize the other format 4) Serialize the newly-created object as a replacement pickle

Installed Versions

INSTALLED VERSIONS ------------------ commit : 2cc37625532045f4ac55b27176454bbbc9baf213 python : 3.11.12 python-bits : 64 OS : Windows OS-release : 10 Version : 10.0.19045 machine : AMD64 processor : Intel64 Family 6 Model 158 Stepping 10, GenuineIntel byteorder : little LC_ALL : None LANG : None LOCALE : English_United States.1252 pandas : 2.3.0 numpy : 2.2.6 pytz : 2025.2 dateutil : 2.9.0.post0 pip : 25.1.1 Cython : None sphinx : None IPython : 9.3.0 adbc-driver-postgresql: None adbc-driver-sqlite : None bs4 : 4.13.4 blosc : None bottleneck : 1.5.0 dataframe-api-compat : None fastparquet : None fsspec : 2025.5.1 html5lib : None hypothesis : None gcsfs : None jinja2 : 3.1.6 lxml.etree : 5.4.0 matplotlib : 3.10.3 numba : 0.61.2+0.g1e70d8ceb.dirty numexpr : 2.10.2 odfpy : None openpyxl : 3.1.5 pandas_gbq : None psycopg2 : None pymysql : None pyarrow : 19.0.1 pyreadstat : None pytest : 8.4.1 python-calamine : None pyxlsb : None s3fs : 2025.5.1 scipy : 1.15.2 sqlalchemy : 2.0.41 tables : None tabulate : 0.9.0 xarray : 2025.6.1 xlrd : None xlsxwriter : 3.2.5 zstandard : 0.23.0 tzdata : 2025.2 qtpy : None pyqt5 : None