I've had that problem recently. It occurs for me when I have multiple data frames that contain some of the same layers. I've fixed this by calling the layers inside the data frames like this:
import arcpy
mxd = arcpy.mapping.MapDocument("CURRENT")
newSdePath = r"Database Connections\My Connection.sde"
for df in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df):
lyr.replaceDataSource(newSdePath, "SDE_WORKSPACE", lyr.datasetName, False)
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
mxd.save()
del mxd
It's also helpful to check that you can use the dataSource and datasetName functions on your layers before attempting replaceDataSource:
import arcpy
mxd = arcpy.mapping.MapDocument("CURRENT")
newSdePath = r"Database Connections\My Connection.sde"
for df in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df):
if (lyr.supports("DATASOURCE") and lyr.supports("datasetName")):
lyr.replaceDataSource(newSdePath, "SDE_WORKSPACE", lyr.datasetName, False)
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
mxd.save()
del mxd
I also had problems with the SDE paths, notably that my features were inside feature classes, and that I wanted to make sure that I was only replacing data sources that were in my old SDE (e.g. not in a file gdb on my local drive), so I came up with this:
import arcpy, os
mxd = arcpy.mapping.MapDocument("CURRENT")
newSdePath = r"Database Connections\My Connection.sde"
oldSdePath = r"Database Connections\My Old Connection.sde"
for df in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df):
if (lyr.supports("DATASOURCE") and lyr.supports("datasetName")):
tempDataSetPath, tempDataSet = os.path.split(lyr.dataSource)
tempDataSetPath, tempDataSetClass = os.path.split(tempDataSetPath)
if lyr.dataSource == os.path.join(oldSdePath, tempDataSetClass, lyr.datasetName):
lyr.replaceDataSource(newSdePath, "SDE_WORKSPACE", lyr.datasetName, False)
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
mxd.save()
del mxd
I hope this is useful.