Activiti saves the status in database when it comes to a wait state. Wait state can be human task, recieve task , asynchronous task and so on or when the process ends.
If for any reason, activiti cannot reach the next wait state, in the next run, it has no way to find out that. So it will start from the last wait sate.
These may cause some steps to be repeated.
If you need some kind of recovery, you have to make sure that BPMN exception is thrown and not java exception.
Then you can catch BPMN exception and forward to a recieve step. Later on, you can resume the process from the latest receive task by sending a signal to the process.