title: Why do I get 'MySQL server has gone away' after running a Telegram bot for some hours?
body: <p>I'm building a Django (ver. 3.0.5) app that uses <code>mysqlclient</code> (ver. 2.0.3) as the DB backend. Additionally, I've written a Django command that runs a bot written using the <a href="https://github.com/python-telegram-bot/python-telegram-bot" rel="nofollow noreferrer">python-telegram-bot</a> API, so the mission of this bot is to run indefinitely, as it has to answer to commands anytime.</p>
  <p>Problem is that approximately 24hrs. after running the bot (not necessarily being idle all the time), I get a <code>django.db.utils.OperationalError: (2006, 'MySQL server has gone away')</code> exception after running any command.</p>
  <p>I'm absolutely sure the MySQL server has been running all the time and is still running at the time I get this exception. The MySQL server version is <code>5.7.35</code>.</p>
  <p>My assumption is that some MySQL threads get aged out and get closed, so after reusing them they won't get renewed.</p>
  <p>Has anyone bumped into this situation and knows how to solve it?</p>
  <pre><code>Traceback (most recent call last):
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/telegram/ext/dispatcher.py&quot;, line 555, in process_update
      handler.handle_update(update, self, check, context)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/telegram/ext/handler.py&quot;, line 198, in handle_update
      return self.callback(update, context)
    File &quot;/opt/django/gip/gip/hospital/gipcrbot.py&quot;, line 114, in ayuda
      perfil = get_permiso_efectivo(update.message.from_user.id)
    File &quot;/opt/django/gip/gip/hospital/telegram/funciones.py&quot;, line 33, in get_permiso_efectivo
      u = Telegram.objects.get(idtelegram=userid)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/models/manager.py&quot;, line 82, in manager_method
      return getattr(self.get_queryset(), name)(*args, **kwargs)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/models/query.py&quot;, line 411, in get
      num = len(clone)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/models/query.py&quot;, line 258, in __len__
      self._fetch_all()
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/models/query.py&quot;, line 1261, in _fetch_all
      self._result_cache = list(self._iterable_class(self))
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/models/query.py&quot;, line 57, in __iter__
      results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/models/sql/compiler.py&quot;, line 1151, in execute_sql
      cursor.execute(sql, params)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/backends/utils.py&quot;, line 100, in execute
      return super().execute(sql, params)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/backends/utils.py&quot;, line 68, in execute
      return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/backends/utils.py&quot;, line 77, in _execute_with_wrappers
      return executor(sql, params, many, context)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/backends/utils.py&quot;, line 86, in _execute
      return self.cursor.execute(sql, params)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/utils.py&quot;, line 90, in __exit__
      raise dj_exc_value.with_traceback(traceback) from exc_value
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/backends/utils.py&quot;, line 86, in _execute
      return self.cursor.execute(sql, params)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/django/db/backends/mysql/base.py&quot;, line 74, in execute
      return self.cursor.execute(query, args)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/MySQLdb/cursors.py&quot;, line 206, in execute
      res = self._query(query)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/MySQLdb/cursors.py&quot;, line 319, in _query
      db.query(q)
    File &quot;/opt/django/gip/venv/lib/python3.6/site-packages/MySQLdb/connections.py&quot;, line 259, in query
      _mysql.connection.query(self, query)
  django.db.utils.OperationalError: (2006, 'MySQL server has gone away')
  </code></pre>
  <h2><strong>Things I have tried</strong></h2>
  <p>I already tried changing the Django settings.py file so I set an explicit value for <code>CONN_MAX_AGE</code>, and I also set a value for the MySQL client <code>wait_timeout</code> parameter, being <code>CONN_MAX_AGE</code> lower than <code>wait_timeout</code>.</p>
  <p><strong>settings.py</strong>:</p>
  <pre><code>DATABASES = {
      'default': {
          'ENGINE': 'django.db.backends.mysql',
          'OPTIONS': {
              'read_default_file': '/opt/django/gip/gip/gip/my.cnf',
          },
          'CONN_MAX_AGE': 3600,
      }
  }
  </code></pre>
  <p><strong>my.cnf</strong>:</p>
  <pre><code>[client]
  ...
  wait_timeout = 28800
  </code></pre>
  <p>Unfortunately, the behavior is exactly the same: I get an exception approximately 24hrs. after running the bot.</p>
  <hr />
  <p>Setting <code>CONN_MAX_AGE</code> to <code>None</code> won't make any difference either.</p>
  <hr />
  <p>I installed the <code>mysql-server-has-gone-away</code> python package as proposed by @r-marolahy, but it won't make a difference either. After nearly 24hours after running it the &quot;gone away&quot; message shows again.</p>
  <hr />
  <p>I also tried the approach of closing old connections:</p>
  <pre><code>from django.db import close_old_connections
  
  try:
      #do your long running operation here
  except django.db.utils.OperationalError:
      close_old_connections()
      #do your long running operation here
  </code></pre>
  <p>Still getting the same result.</p>