I was recently tasked with investigating a mysterious error on a customer's site, which I finally tracked down to an oversight in the upgrade process of a DotNetNuke module. The error threw up a YSOD, (though in later testing on a different site, it also showed up in a regular DNN red triangle error message), with an error message like "Multiple controls with the same ID 'ctr376' were found. FindControl requires that controls have unique IDs." Talking it through with Chris, we figured out that there were two entries in this module definition for the same control key. So, when we tried to go to the Edit control, DNN was attempting to load two different .ascx controls in the Admin control, which caused the whole thing to kind of blow up and die.
So, how did we get two controls registered for the same control key? The answer was obvious enough, probably because it's bit me before: upgrades. When you upgrade a module in DNN, the installer adds any new control definitions that it finds in your module's manifest file. It doesn't, however, remove control definitions that it doesn't find any more. This means that if you rename a ControlKey, or, as in this case, you rename a control itself, you'll have duplicate entries pointing to incorrect information. Most of the time this isn't too much of an issue, but sometimes it'll cause mysterious errors that take up your morning before you figure them out.
The solution: Be aware when you are renaming or removing any entries from your module's manifest. When you find yourself renaming, make sure that you add a line to that version's SQL script to remove the old entry from the database. At the very least this keeps your module definition clean, and it also avoids nasty, hard-to-track-down bugs. This would look something like
DELETE {databaseOwner}[{objectQualifier}ModuleControls]
WHERE ControlKey = 'Edit'
AND ControlSrc = 'DesktopModules/EngageSample/Edit.ascx'
One other note, if you rename or remove a control from your module, there's also a mechanism to have those removed from the site upon upgrade. If you add a text file with the name of the version to your module (and to your manifest's files section), DNN will look for any files listed in that file, and delete them if it finds them. For example, if I rename Edit.ascx to EditSample.ascx in version 02.02.05 of a module, I can add 02.02.05.txt to the module package and manifest. This file would contain one line, "DesktopModules/EngageSample/Edit.ascx" and I could add additional lines for other files, including files in the bin folder, if I needed to. Upon uploading the new 02.02.05 module package, no more Edit.ascx.
These two techniques, applied together, can help keep your module nice and tidy as you upgrade, and keep all of those mysterious, day-stealing errors away.
Hope it helps!