It is a tough call.
Obligatory Joel reference: Things You Should Never Do, Part I
That said, there are of course cases when it is still better to rewrite from scratch than to keep fixing the fundamentally broken. If all of the following applies to your case, you probably have a reason to rewrite from scratch:
- there are no automated tests,
- the original project team is gone, and noone knows how the product is implemented, thus making any changes is incredibly difficult and results are unpredictable,
- the product is so low quality that replacing it with a new, necessarily bug-fraught implementation would not make a major difference,
- the technology used is obsolete, and there is a pressing need to replace it with something new (e.g. in order to enable some desired major feature, or to deploy it on a new platform - @Thorbjörn's answer@Thorbjörn's answer contains a good example for the latter).
(If only some of these applies... well, that's the tough one to decide, and there is no general answer there.) At any rate, you would also need the following conditions to give you at least a chance of making such a move successful:
- time-to-market is not an issue - customers are patient enough to wait a looong time for a promised, fundamentally better version and there are no competitors,
- there exists live, detailed knowledge (ideally in well written specifications, but also in several people's heads - and these people are accessible to answer developers' questions) on how the damn thing should actually behave in any specific situation,
- management is at least open to the idea, and ideally they understand the potential costs vs benefits.
All in all, you must take into account that a complete rewrite from scratch is going to take a lot more time, effort and pain than anticipated. So if you can, try to partition the job into smaller chunks, to replace only modules/components of the old code one by one. This way
- you can start by building a suite of regression tests around the existing program, which then make it much easier to preserve (and if necessary, improve) the old functionality with the new code,
- you will have a working, up-to-date program most of the time (thus way happier users and management),
- you may save rewriting (potentially significant) parts of the code which do not need to change and "just work".