Thanks for the pointers. I hadn't spotted that caveat in the Profiling help page, as the exception was being raised in other places like CodeTools:-Profiling:-Coverage:-Print, CodeTools:-DecodeName and the like. I've tried the named module suggestion, and it looks like it's going to work, without the nuisance of putting the module into a repository.
It could be that the two workarounds you suggested are related. The help page for module,named says: "Every module that is saved to a repository is given a name (that under which it was saved) for use by the persistent store." So perhaps the reason why packages in the repository work is that they are named?
In fact we had a third workaround, along the following lines...
m := module() option package; export f; f := proc() end proc; end module;
fcopy := op(m:-f);
[now work with fcopy for profiling purposes]
But named module is cleaner. Thanks again for your help, we now have something we can work with.