# Buggy code
def flush_queued_events(self, retry_count=0):
    """Flush all queued events.

    Returns:
        dict: A dict object that contains the number of events
            that were sent to Elastic as well as information
            on whether there were any errors, and what the
            details of these errors if any.
        retry_count: optional int indicating whether this is a retry.
    """
    if not self.import_events:
        return {}

    return_dict = {
        "number_of_events": len(self.import_events) / 2,
        "total_events": self.import_counter["events"],
    }

    try:
        results = self.client.bulk(body=self.import_events)
    except (ConnectionTimeout, socket.timeout):
        if retry_count >= self.DEFAULT_FLUSH_RETRY_LIMIT:
            es_logger.error("Unable to add events, reached recount max.", exc_info=True)
            return {}

        es_logger.error(
            "Unable to add events (retry {0:d}/{1:d})".format(
                retry_count, self.DEFAULT_FLUSH_RETRY_LIMIT
            )
        )
        return self.flush_queued_events(retry_count + 1)

    errors_in_upload = results.get("errors", False)
    return_dict["errors_in_upload"] = errors_in_upload

    if errors_in_upload:
        items = results.get("items", [])
        return_dict["errors"] = []

        es_logger.error("Errors while attempting to upload events.")
        for item in items:
            index = item.get("index", {})
            index_name = index.get("_index", "N/A")

            _ = self._error_container.setdefault(
                index_name, {"errors": [], "types": Counter(), "details": Counter()}
            )

            error_counter = self._error_container[index_name]["types"]
            error_detail_counter = self._error_container[index_name]["details"]
            error_list = self._error_container[index_name]["errors"]

            error = index.get("error", {})
            status_code = index.get("status", 0)
            doc_id = index.get("_id", "(unable to get doc id)")
            caused_by = error.get("caused_by", {})

            caused_reason = caused_by.get("reason", "Unkown Detailed Reason")

            error_counter[error.get("type")] += 1
            detail_msg = "{0:s}/{1:s}".format(
                caused_by.get("type", "Unknown Detailed Type"),
                " ".join(caused_reason.split()[:5]),
            )
            error_detail_counter[detail_msg] += 1

            error_msg = "<{0:s}> {1:s} [{2:s}/{3:s}]".format(
                error.get("type", "Unknown Type"),
                error.get("reason", "No reason given"),
                caused_by.get("type", "Unknown Type"),
                caused_reason,
            )
            error_list.append(error_msg)
            try:
                es_logger.error(
                    "Unable to upload document: {0:s} to index {1:s} - "
                    "[{2:d}] {3:s}".format(doc_id, index_name, status_code, error_msg)
                )
            # We need to catch all exceptions here, since this is a crucial
            # call that we do not want to break operation.
            except Exception:  # pylint: disable=broad-except
                es_logger.error(
                    "Unable to upload document, and unable to log the error itself.",
                    exc_info=True,
                )

    return_dict["error_container"] = self._error_container

    self.import_events = []
    return return_dict


# Traceback (urllib3.exceptions.ReadTimeoutError)
[2021-01-21 09:57:16,813] celery.worker.strategy/INFO Received task: timesketch.lib.tasks.run_csv_jsonl[34b8f46651b94a8d8ad9e29bb06a147c]
[2021-01-21 09:57:16,819] timesketch.tasks/INFO Index timeline [vol timeline] to index [34b8f46651b94a8d8ad9e29bb06a147c] (source: jsonl)
[2021-01-21 09:58:14,763] timesketch.elasticsearch/ERROR Unable to add events
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 421, in _make_request
six.raise_from(e, None)
File "<string>", line 3, in raise_from
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 416, in _make_request
httplib_response = conn.getresponse()
File "/usr/lib/python3.8/http/client.py", line 1347, in getresponse
response.begin()
File "/usr/lib/python3.8/http/client.py", line 307, in begin
version, status, reason = self._read_status()
File "/usr/lib/python3.8/http/client.py", line 268, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/usr/lib/python3.8/socket.py", line 669, in readinto
return self._sock.recv_into(b)
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/elasticsearch/connection/http_urllib3.py", line 241, in perform_request
response = self.pool.urlopen(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 719, in urlopen
retries = retries.increment(
File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 376, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/usr/local/lib/python3.8/dist-packages/six.py", line 693, in reraise
raise value
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 665, in urlopen
httplib_response = self._make_request(
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 423, in _make_request
self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 330, in _raise_timeout
raise ReadTimeoutError(
urllib3.exceptions.ReadTimeoutError: HTTPConnectionPool(host='elasticsearch', port=9200): Read timed out. (read timeout=10)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/timesketch/lib/datastores/elastic.py", line 830, in flush_queued_events
results = self.client.bulk(body=self.import_events)
File "/usr/local/lib/python3.8/dist-packages/elasticsearch/client/utils.py", line 84, in _wrapped
return func(*args, params=params, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/elasticsearch/client/__init__.py", line 448, in bulk
return self.transport.perform_request(
File "/usr/local/lib/python3.8/dist-packages/elasticsearch/transport.py", line 351, in perform_request
status, headers_response, data = connection.perform_request(
File "/usr/local/lib/python3.8/dist-packages/elasticsearch/connection/http_urllib3.py", line 253, in perform_request
raise ConnectionTimeout("TIMEOUT", str(e), e)
elasticsearch.exceptions.ConnectionTimeout: ConnectionTimeout caused by - ReadTimeoutError(HTTPConnectionPool(host='elasticsearch', port=9200): Read timed out. (read timeout=10))
[2021-01-21 09:58:15,185] celery.app.trace/ERROR Task timesketch.lib.tasks.run_csv_jsonl[34b8f46651b94a8d8ad9e29bb06a147c] raised unexpected: UnboundLocalError("local variable 'results' referenced before assignment")
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/celery/app/trace.py", line 385, in trace_task
R = retval = fun(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/timesketch/app.py", line 198, in __call__
return TaskBase.__call__(self, *args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/celery/app/trace.py", line 650, in __protected_call__
return self.run(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/timesketch/lib/tasks.py", line 563, in run_csv_jsonl
results = es.flush_queued_events()
File "/usr/local/lib/python3.8/dist-packages/timesketch/lib/datastores/elastic.py", line 835, in flush_queued_events
errors_in_upload = results.get('errors', False)
UnboundLocalError: local variable 'results' referenced before assignment

# Fixed code
def flush_queued_events(self, retry_count=0):
    """Flush all queued events.

    Returns:
        dict: A dict object that contains the number of events
            that were sent to Elastic as well as information
            on whether there were any errors, and what the
            details of these errors if any.
        retry_count: optional int indicating whether this is a retry.
    """
    if not self.import_events:
        return {}

    return_dict = {
        "number_of_events": len(self.import_events) / 2,
        "total_events": self.import_counter["events"],
    }

    try:
        # pylint: disable=unexpected-keyword-arg
        results = self.client.bulk(
            body=self.import_events, timeout=self._request_timeout
        )
    except (ConnectionTimeout, socket.timeout):
        if retry_count >= self.DEFAULT_FLUSH_RETRY_LIMIT:
            es_logger.error("Unable to add events, reached recount max.", exc_info=True)
            return {}

        es_logger.error(
            "Unable to add events (retry {0:d}/{1:d})".format(
                retry_count, self.DEFAULT_FLUSH_RETRY_LIMIT
            )
        )
        return self.flush_queued_events(retry_count + 1)

    errors_in_upload = results.get("errors", False)
    return_dict["errors_in_upload"] = errors_in_upload

    if errors_in_upload:
        items = results.get("items", [])
        return_dict["errors"] = []

        es_logger.error("Errors while attempting to upload events.")
        for item in items:
            index = item.get("index", {})
            index_name = index.get("_index", "N/A")

            _ = self._error_container.setdefault(
                index_name, {"errors": [], "types": Counter(), "details": Counter()}
            )

            error_counter = self._error_container[index_name]["types"]
            error_detail_counter = self._error_container[index_name]["details"]
            error_list = self._error_container[index_name]["errors"]

            error = index.get("error", {})
            status_code = index.get("status", 0)
            doc_id = index.get("_id", "(unable to get doc id)")
            caused_by = error.get("caused_by", {})

            caused_reason = caused_by.get("reason", "Unkown Detailed Reason")

            error_counter[error.get("type")] += 1
            detail_msg = "{0:s}/{1:s}".format(
                caused_by.get("type", "Unknown Detailed Type"),
                " ".join(caused_reason.split()[:5]),
            )
            error_detail_counter[detail_msg] += 1

            error_msg = "<{0:s}> {1:s} [{2:s}/{3:s}]".format(
                error.get("type", "Unknown Type"),
                error.get("reason", "No reason given"),
                caused_by.get("type", "Unknown Type"),
                caused_reason,
            )
            error_list.append(error_msg)
            try:
                es_logger.error(
                    "Unable to upload document: {0:s} to index {1:s} - "
                    "[{2:d}] {3:s}".format(doc_id, index_name, status_code, error_msg)
                )
            # We need to catch all exceptions here, since this is a crucial
            # call that we do not want to break operation.
            except Exception:  # pylint: disable=broad-except
                es_logger.error(
                    "Unable to upload document, and unable to log the error itself.",
                    exc_info=True,
                )

    return_dict["error_container"] = self._error_container

    self.import_events = []
    return return_dict