{"slug": "my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing", "title": "My Algorithmic Trading Bot Silently Failed to Notify: The Curious Case of Missing `.env` Loads Across Scripts", "summary": "A developer discovered a silent failure in an AI-powered algorithmic trading bot where Discord notifications for order confirmations were not firing due to a missing `load_dotenv()` call in `executor.py`. The bug, which could have caused catastrophic issues with real capital, was traced to an implicit dependency on `.env` variables loaded by another script. The fix involved adding `load_dotenv(find_dotenv())` to ensure the webhook URL is set before sending notifications.", "body_md": "Hey everyone, it's your friendly neighborhood senior dev here. I'm 38, working as a full-time engineer during the week, and tinkering with AI-powered algorithmic trading bots on the weekends.\n\nToday, I want to share a story about a subtle but potentially catastrophic bug I found in my bot. Seriously, thank goodness I caught this before deploying with real capital. The TL;DR: My Discord notifications for order confirmations weren't firing, and the culprit was a forgotten `.env`\n\nload across multiple Python scripts.\n\nI think this is a pretty common pitfall when you're working on personal projects with several interconnected Python scripts.\n\nOver the weekend, I was running my usual DRY_RUN tests for my forex bot. My bot's architecture splits responsibilities: `planner.py`\n\nhandles strategy logic, and `executor.py`\n\nexecutes actual trades on the exchange.\n\nLooking at the console logs, `executor.py`\n\nseemed to be working perfectly. I saw logs like `[DRY_RUN] Order placed: ...`\n\n. But the Discord notifications, which are supposed to arrive after an order, simply weren't showing up.\n\nInitially, I thought it might be a Discord issue or just a delay. But after 30 minutes, still nothing. This felt wrong.\n\nThe thought of this happening with real money sent shivers down my spine:\n\nBugs in notification systems are notorious for creating these kinds of silent failures, and they're genuinely scary.\n\nMy first step was to isolate the problem. I directly invoked `notify.py`\n\n, the script responsible for sending notifications. It worked perfectly, sending a test message to Discord. This strongly suggested the issue was upstream, likely within `executor.py`\n\n, which calls `notify.py`\n\n.\n\nI took a closer look at `executor.py`\n\n's logs. And there it was: the webhook URL, which should have been passed to the notification function, was `None`\n\n. Bingo.\n\nBut why `None`\n\n? I store my webhook URL in a `.env`\n\nfile, and other scripts, like `planner.py`\n\n, were successfully reading it. So I compared the code for `planner.py`\n\nand `executor.py`\n\n.\n\nAnd I immediately spotted the difference. At the beginning of `planner.py`\n\n, there was a clear `load_dotenv()`\n\ncall:\n\n``` python\n# ...\nfrom dotenv import load_dotenv\n\nload_dotenv() # Load environment variables\n\n# ... planner logic ...\n```\n\nHowever, `executor.py`\n\n, the script in question, was missing this `load_dotenv()`\n\ncall.\n\nThis meant that when I ran the entire flow starting from `planner.py`\n\n, `planner.py`\n\nwould load the `.env`\n\nvariables, making them available to `executor.py`\n\n. But if I ran `executor.py`\n\ndirectly for testing, or if it was called from a different entry point, no one was loading the `.env`\n\nfile. Consequently, the webhook URL was never set, and notifications failed silently.\n\nMy code had an implicit dependency, and that's a dangerous path. If this were a team project, it would definitely be caught in code review. But when you're working solo, these kinds of things can easily slip through.\n\nOnce the cause was clear, the fix was straightforward. I added `load_dotenv()`\n\nto `executor.py`\n\nbefore calling the notification logic.\n\nBefore (simplified):\n\n```\n// Before: Calling notification function without loading .env\nfrom .notify import hub\n\nhub.notify_investment('Execution result...') # Fails because webhook is not set\n```\n\nIn this setup, when the `hub`\n\nmodule initializes, `os.environ.get('DISCORD_WEBHOOK_INVESTMENT')`\n\nreturns `None`\n\n, leading to a silent notification failure.\n\nAfter (simplified):\n\n``` python\n// After: Loading .env before notification\nimport os\nfrom dotenv import load_dotenv, find_dotenv\nfrom .notify import hub\n\n# Find .env file and load environment variables.\n# This ensures the webhook URL is set in os.environ.\nif 'DISCORD_WEBHOOK_INVESTMENT' not in os.environ: # Only load if not already set\n    load_dotenv(find_dotenv())\n\nhub.notify_investment('Execution result...') # Notification sent successfully\n```\n\nI used `find_dotenv()`\n\nto ensure that the `.env`\n\nfile is located correctly, regardless of the current working directory during execution. This guarantees that `executor.py`\n\ncan always find and load the webhook URL, no matter how it's invoked.\n\nIt's a fundamental principle, but it's always good to be reminded: code that depends on certain features (like environment variables) should take responsibility for resolving those dependencies (loading them) where they are used.\n\nThis incident taught me three important lessons:\n\n**DRY_RUN Tests Are God-Tier**\n\nThe value of discovering \"normal-looking anomalies\" without any financial cost is immense. Things that *look* like they're working are the most dangerous. Never skip DRY_RUN tests before production deployment.\n\n**Eliminate \"Implicit Assumptions\" Between Scripts**\n\nWhen you split code into multiple files, it's easy to develop implicit assumptions like, \"Oh, that other file will initialize it.\" For project-wide settings like `.env`\n\n, it's better design to explicitly load them at each entry point or at the beginning of the modules that rely on them.\n\n**Consider Assertions for Critical Operations**\n\nWhile I caught this with logs, for even more robustness, it might be worth adding an assertion like `assert os.environ.get('DISCORD_WEBHOOK_INVESTMENT') is not None`\n\nright before critical operations like placing an order or sending a notification. This can catch misconfigurations immediately.\n\nOperating a personal bot is a continuous battle against these subtle bugs. But each one I squash makes the system stronger. It was another weekend where my bot got a little smarter.\n\nOji / AI Algo Trading Engineer\n\nX: @oji_ai_dev", "url": "https://wpnews.pro/news/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing", "canonical_source": "https://dev.to/masaoshimadaopen/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing-env-loads-55p1", "published_at": "2026-08-05 06:25:35+00:00", "updated_at": "2026-08-05 06:47:22.125024+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Discord", "Python", "dotenv"], "alternates": {"html": "https://wpnews.pro/news/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing", "markdown": "https://wpnews.pro/news/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing.md", "text": "https://wpnews.pro/news/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing.txt", "jsonld": "https://wpnews.pro/news/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing.jsonld"}}