def fail(self, tup_id):
saved_args = self.unacked_tuples.get(tup_id)<EOL>if saved_args is None:<EOL><INDENT>self.logger.error("<STR_LIT>", tup_id)<EOL>return<EOL><DEDENT>tup, stream, direct_task, need_task_ids = saved_args<EOL>if self.failed_tuples[tup_id] < self.max_fails:<EOL><INDENT>self.emit(<EOL>tup,<EOL>tup_id=tup_id,<EOL>stream=stream,<EOL>direct_task=direct_task,<EOL>need_task_ids=need_task_ids,<EOL>)<EOL>self.failed_tuples[tup_id] += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>self.logger.info(<EOL>"<STR_LIT>" "<STR_LIT>",<EOL>tup_id,<EOL>self.max_fails,<EOL>)<EOL>self.ack(tup_id)<EOL><DEDENT>
Called when a Tuple fails in the topology

        A reliable spout will replay a failed tuple up to ``max_fails`` times.

        :param tup_id: the ID of the Tuple that has failed in the topology
                       either due to a bolt calling ``fail()`` or a Tuple
                       timing out.
        :type tup_id: str