For the tasks that take too long to launch (for genuine reasons like large distributed caches), JT expires the task. Depending on whether job recovery is enabled and the JT's restart state, another attempt is launched or not even when the JT is not restarted. The status of the attempt changes to "Error launching task". Meanwhile, the TT is not informed of this task expiry and eventually launches the task. Also, the "new" attempt might be assigned to the same TT leading to more inconsistent behavior.
To avoid this, one can bump up the mapred.tasktracker.expiry.interval, but leading to long TT failure discovery times.
We should have a per-job timeout for task launches/ heartbeat and JT/TT should be consistent in what they say.