# My Algorithmic Trading Bot Silently Failed to Notify: The Curious Case of Missing `.env` Loads Across Scripts

> Source: <https://dev.to/masaoshimadaopen/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing-env-loads-55p1>
> Published: 2026-08-05 06:25:35+00:00

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.

Today, 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`

load across multiple Python scripts.

I think this is a pretty common pitfall when you're working on personal projects with several interconnected Python scripts.

Over the weekend, I was running my usual DRY_RUN tests for my forex bot. My bot's architecture splits responsibilities: `planner.py`

handles strategy logic, and `executor.py`

executes actual trades on the exchange.

Looking at the console logs, `executor.py`

seemed to be working perfectly. I saw logs like `[DRY_RUN] Order placed: ...`

. But the Discord notifications, which are supposed to arrive after an order, simply weren't showing up.

Initially, I thought it might be a Discord issue or just a delay. But after 30 minutes, still nothing. This felt wrong.

The thought of this happening with real money sent shivers down my spine:

Bugs in notification systems are notorious for creating these kinds of silent failures, and they're genuinely scary.

My first step was to isolate the problem. I directly invoked `notify.py`

, 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`

, which calls `notify.py`

.

I took a closer look at `executor.py`

's logs. And there it was: the webhook URL, which should have been passed to the notification function, was `None`

. Bingo.

But why `None`

? I store my webhook URL in a `.env`

file, and other scripts, like `planner.py`

, were successfully reading it. So I compared the code for `planner.py`

and `executor.py`

.

And I immediately spotted the difference. At the beginning of `planner.py`

, there was a clear `load_dotenv()`

call:

``` python
# ...
from dotenv import load_dotenv

load_dotenv() # Load environment variables

# ... planner logic ...
```

However, `executor.py`

, the script in question, was missing this `load_dotenv()`

call.

This meant that when I ran the entire flow starting from `planner.py`

, `planner.py`

would load the `.env`

variables, making them available to `executor.py`

. But if I ran `executor.py`

directly for testing, or if it was called from a different entry point, no one was loading the `.env`

file. Consequently, the webhook URL was never set, and notifications failed silently.

My 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.

Once the cause was clear, the fix was straightforward. I added `load_dotenv()`

to `executor.py`

before calling the notification logic.

Before (simplified):

```
// Before: Calling notification function without loading .env
from .notify import hub

hub.notify_investment('Execution result...') # Fails because webhook is not set
```

In this setup, when the `hub`

module initializes, `os.environ.get('DISCORD_WEBHOOK_INVESTMENT')`

returns `None`

, leading to a silent notification failure.

After (simplified):

``` python
// After: Loading .env before notification
import os
from dotenv import load_dotenv, find_dotenv
from .notify import hub

# Find .env file and load environment variables.
# This ensures the webhook URL is set in os.environ.
if 'DISCORD_WEBHOOK_INVESTMENT' not in os.environ: # Only load if not already set
    load_dotenv(find_dotenv())

hub.notify_investment('Execution result...') # Notification sent successfully
```

I used `find_dotenv()`

to ensure that the `.env`

file is located correctly, regardless of the current working directory during execution. This guarantees that `executor.py`

can always find and load the webhook URL, no matter how it's invoked.

It'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.

This incident taught me three important lessons:

**DRY_RUN Tests Are God-Tier**

The 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.

**Eliminate "Implicit Assumptions" Between Scripts**

When 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`

, it's better design to explicitly load them at each entry point or at the beginning of the modules that rely on them.

**Consider Assertions for Critical Operations**

While 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`

right before critical operations like placing an order or sending a notification. This can catch misconfigurations immediately.

Operating 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.

Oji / AI Algo Trading Engineer

X: @oji_ai_dev
