BrokenPipeError when using telegram-bot-api server with Docker

Hi

I’m deploying a Docker Container that builds tdlib/telegram-bot-api server.

I’ve another bot (based on python-telegram-bot library). This bot sends files/videos/audios etc to the user. When I connect this bot:

  1. to official telegram-bot server (api.telegram.org), everything works fine.
  2. to the telegram-bot-api server (hosted on my local-machine or heroku.com), everything works fine.
  3. to the telegram-bot-api server (hosted on fly.io):
    • Sending the files/audios/videos etc throws BrokenPipeError.
    • Note: This error occurs only sometimes, and sometimes it doesn’t occur.
    • Even if you send the same file, to same user, with same code, without changing anything.

Method I use to send files from my bot

Chat.send_document(....)		# to send files
Chat.send_audio(....)			# to send audio
Chat.send_video(....)			# to send video
# etc

My Docker file (based on aiogram/aiogram)

FROM alpine:3.12 as build

ENV CXXFLAGS=""
WORKDIR /usr/src/telegram-bot-api

RUN apk add --no-cache --update \
  alpine-sdk linux-headers openssl-dev \
  git zlib-dev gperf cmake
COPY telegram-bot-api /usr/src/telegram-bot-api
RUN mkdir -p build \
  && cd build \
  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=.. .. \
  && cmake --build . --target install -j $(nproc) \
  && strip /usr/src/telegram-bot-api/bin/telegram-bot-api

FROM alpine:3.12

ENV TELEGRAM_WORK_DIR="/var/lib/telegram-bot-api" \
    TELEGRAM_TEMP_DIR="/tmp/telegram-bot-api"

RUN apk add --no-cache --update \
  openssl libstdc++
COPY --from=build /usr/src/telegram-bot-api/bin/telegram-bot-api /usr/local/bin/telegram-bot-api
COPY init-server.sh /init-server.sh
RUN addgroup -g 101 -S telegram-bot-api \
 && adduser -S -D -H -u 101 -h ${TELEGRAM_WORK_DIR} -s /sbin/nologin -G telegram-bot-api -g telegram-bot-api telegram-bot-api \
 && chmod +x /init-server.sh \
 && mkdir -p ${TELEGRAM_WORK_DIR} ${TELEGRAM_TEMP_DIR} \
 && chown telegram-bot-api:telegram-bot-api ${TELEGRAM_WORK_DIR} ${TELEGRAM_TEMP_DIR}

EXPOSE 8081/tcp 8082/tcp
ENTRYPOINT ["/init-server.sh"]

My init-server.sh

#!/bin/sh
set -e

USERNAME=telegram-bot-api
GROUPNAME=telegram-bot-api

chown ${USERNAME}:${GROUPNAME} "${TELEGRAM_WORK_DIR}"

if [ -n "${1}" ]; then
  exec "${*}"
fi

DEFAULT_ARGS="--http-port 8081 --dir=${TELEGRAM_WORK_DIR} --temp-dir=${TELEGRAM_TEMP_DIR} --username=${USERNAME} --groupname=${GROUPNAME}"
CUSTOM_ARGS=""

if [ -n "$TELEGRAM_LOG_FILE" ]; then
  CUSTOM_ARGS="--log=${TELEGRAM_LOG_FILE}"
fi
if [ -n "$TELEGRAM_STAT" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --http-stat-port=8082"
fi
if [ -n "$TELEGRAM_FILTER" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --filter=$TELEGRAM_FILTER"
fi
if [ -n "$TELEGRAM_MAX_WEBHOOK_CONNECTIONS" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --max-webhook-connections=$TELEGRAM_MAX_WEBHOOK_CONNECTIONS"
fi
if [ -n "$TELEGRAM_VERBOSITY" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --verbosity=$TELEGRAM_VERBOSITY"
fi
if [ -n "$TELEGRAM_MAX_CONNECTIONS" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --max-connections=$TELEGRAM_MAX_CONNECTIONS"
fi
if [ -n "$TELEGRAM_PROXY" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --proxy=$TELEGRAM_PROXY"
fi
if [ -n "$TELEGRAM_LOCAL" ]; then
  CUSTOM_ARGS="${CUSTOM_ARGS} --local"
fi


# Increase swap size to %20 of available space (set the SWAP environment variable)
# (this is only required on fly.io)
if [[ ! -z "$SWAP" ]]; then
  fallocate -l $(($(stat -f -c "(%a*%s/10)*2" .))) _swapfile
  mkswap _swapfile
  swapon _swapfile
fi

COMMAND="telegram-bot-api ${DEFAULT_ARGS}${CUSTOM_ARGS}"

echo "$COMMAND"
# shellcheck disable=SC2086
exec $COMMAND

My fly.toml

app = "<appname>"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[env]
  SWAP="true"
  PORT=8081
  TELEGRAM_API_ID="<api-id-here>"
  TELEGRAM_API_HASH="<api-hash-here>"
  TELEGRAM_LOCAL="--local"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  http_checks = []
  tcp_checks = []
  internal_port = 8081
  processes = ["app"]
  protocol = "tcp"
  script_checks = []

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443
  
  [[services.ports]]
    handlers = ["tls", "http"]
    port = 8081

[[services]]
  http_checks = []
  tcp_checks = []
  internal_port = 8082
  processes = ["app"]
  protocol = "tcp"
  script_checks = []

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 8082

Error Traceback from my bot

Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 614, in urlopen
    httplib_response = self._make_request(conn, method, url,
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 390, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.10/http/client.py", line 1282, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1328, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1277, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1076, in _send_output
    self.send(chunk)
  File "/usr/lib/python3.10/http/client.py", line 998, in send
    self.sock.sendall(data)
BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/telegram/utils/request.py", line 259, in _request_wrapper
    resp = self._con_pool.request(*args, **kwargs)
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/request.py", line 68, in request
    return self.request_encode_body(method, url, fields=fields,
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/request.py", line 148, in request_encode_body
    return self.urlopen(method, url, **extra_kw)
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/poolmanager.py", line 244, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 665, in urlopen
    retries = retries.increment(method, url, error=e, _pool=self,
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/util/retry.py", line 347, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/packages/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 614, in urlopen
    httplib_response = self._make_request(conn, method, url,
  File "/usr/lib/python3.10/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 390, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.10/http/client.py", line 1282, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1328, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1277, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1076, in _send_output
    self.send(chunk)
  File "/usr/lib/python3.10/http/client.py", line 998, in send
    self.sock.sendall(data)
telegram.vendor.ptb_urllib3.urllib3.exceptions.ProtocolError: ('Connection aborted.', BrokenPipeError(32, 'Broken pipe'))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/bot/src/mini_apps/yt.py", line 53, in wrapper
    return func(self, *args, **kwargs)
  File "/bot/src/mini_apps/yt.py", line 324, in _post_downloading_fctn
    self.chat.send_audio(
  File "/usr/lib/python3.10/site-packages/telegram/chat.py", line 1088, in send_audio
    return self.bot.send_audio(
  File "/usr/lib/python3.10/site-packages/telegram/bot.py", line 134, in decorator
    result = func(*args, **kwargs)
  File "/usr/lib/python3.10/site-packages/telegram/bot.py", line 886, in send_audio
    return self._message(  # type: ignore[return-value]
  File "/usr/lib/python3.10/site-packages/telegram/ext/extbot.py", line 203, in _message
    result = super()._message(
  File "/usr/lib/python3.10/site-packages/telegram/bot.py", line 344, in _message
    result = self._post(endpoint, data, timeout=timeout, api_kwargs=api_kwargs)
  File "/usr/lib/python3.10/site-packages/telegram/bot.py", line 299, in _post
    return self.request.post(
  File "/usr/lib/python3.10/site-packages/telegram/utils/request.py", line 359, in post
    result = self._request_wrapper('POST', url, fields=data, **urlopen_kwargs)
  File "/usr/lib/python3.10/site-packages/telegram/utils/request.py", line 265, in _request_wrapper
    raise NetworkError(f'urllib3 HTTPError {error}') from error
telegram.error.NetworkError: urllib3 HTTPError ('Connection aborted.', BrokenPipeError(32, 'Broken pipe'))
1 Like