Async Issues with Telethon Bot File Monitoring

I’m building a bot that monitors my computer for file changes and sends notifications through Telegram when something happens.

I decided to use Telethon even though it’s async, but I’m trying to make it work synchronously. My code successfully connects and sends one message in the start() function:

bot.send_message('me', 'Test message works!')

I also have a FileWatcher class with a method that triggers when files change. Right now it just shows a test message:

print("File changed!")

However, when I try to uncomment this line in my file watcher:

#bot.send_message('me', 'File was modified!')

I get runtime errors and both the message sending and console output stop working completely.

Error message:

RuntimeWarning: coroutine 'MessageMethods.send_message' was never awaited
  bot.send_message('me', 'Test message works!')
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

My code:

from telethon import TelegramClient
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
import time

api_id = ****
api_hash = '****'

bot = TelegramClient('Session', api_id, api_hash)

class FileWatcher(FileSystemEventHandler):
    def on_modified(self, event):
        #bot.send_message('me', 'File was modified!')
        print("File changed!")

def start():
    bot.send_message('me', 'Test message works!')
    watcher = Observer()
    watcher.schedule(FileWatcher(), path='/home/user/Documents/', recursive=True)
    watcher.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        watcher.stop()
        watcher.join()

with bot:
    bot.loop.run_until_complete(start())

if __name__ == '__main__':
    start()

What am I doing wrong here?

You’re mixing async and sync code wrong. When you call start() at the bottom, it runs outside the async context - that’s why send_message() fails in your file watcher callback. The with bot: block creates async context, but your direct start() call doesn’t use it. I hit the same issues when I started with Telethon. You need to either make everything async or use asyncio.run_coroutine_threadsafe() to bridge the gap. For your file watcher callback, try asyncio.create_task(bot.send_message('me', 'File was modified!')) but make sure you’re in an async context first. Better yet, use a queue system - let the file watcher add events to a queue, then have your main async loop process them. This keeps async/sync boundaries clean and stops those runtime warnings.

You’re calling start() twice - once in the with bot: block and again after if __name__ == '__main__':. Drop that second call. Also make your start function async and use await bot.send_message(). Your file callback won’t work unless it runs in the same event loop.

Your FileWatcher callback runs outside Telethon’s event loop - that’s the problem. When the file changes and triggers on_modified(), there’s no async context to handle the coroutine. I hit this same issue building a monitoring system last year. Here’s what worked: store messages in a simple queue from the file watcher, then have a separate async task poll that queue and send the Telegram messages. Use queue.Queue for thread-safe communication between your sync file watcher and async Telethon client. Create a background task that runs await asyncio.sleep(0.1) in a loop, checks for queued messages, and sends them through Telethon. This keeps file monitoring synchronous while maintaining proper async message sending - no more coroutine warnings.