You're current knowledge about activiti being asynchronous (by default) is wrong. When you start a process (or complete a task), the current thread is used to execute the next steps of the process, until another wait-state (task, receive-task, …) or process-end is reached.
So in case you're process has a service-task (some Java behavior) that checks against a 3rd-pary system, after a user-task, the call to our "taskService.complete()" will only return, after that call has been done. If you throw an exception in the service-task that contacts the 3rd party system, this will bubble up to the point where the API-call (completeTask()) is done. On that moment, you can inspect the exception and give the user appropriate feedback (e.g. entity X does not exist in system Y).
Asynchronous behavior is possible in Activiti, but this needs to be explicit ally configured on a per-activity-basis…