<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: oji - building AI in public</title>
    <description>The latest articles on DEV Community by oji - building AI in public (@masaoshimadaopen).</description>
    <link>https://dev.to/masaoshimadaopen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4013207%2F62889ff7-f41e-4077-9836-3fafe971b8ce.jpg</url>
      <title>DEV Community: oji - building AI in public</title>
      <link>https://dev.to/masaoshimadaopen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masaoshimadaopen"/>
    <language>en</language>
    <item>
      <title>My Algorithmic Trading Bot Silently Failed to Notify: The Curious Case of Missing `.env` Loads Across Scripts</title>
      <dc:creator>oji - building AI in public</dc:creator>
      <pubDate>Wed, 05 Aug 2026 06:25:35 +0000</pubDate>
      <link>https://dev.to/masaoshimadaopen/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing-env-loads-55p1</link>
      <guid>https://dev.to/masaoshimadaopen/my-algorithmic-trading-bot-silently-failed-to-notify-the-curious-case-of-missing-env-loads-55p1</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;.env&lt;/code&gt; load across multiple Python scripts.&lt;/p&gt;

&lt;p&gt;I think this is a pretty common pitfall when you're working on personal projects with several interconnected Python scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happened: A "Silent Failure" Uncovered by DRY_RUN
&lt;/h3&gt;

&lt;p&gt;Over the weekend, I was running my usual DRY_RUN tests for my forex bot. My bot's architecture splits responsibilities: &lt;code&gt;planner.py&lt;/code&gt; handles strategy logic, and &lt;code&gt;executor.py&lt;/code&gt; executes actual trades on the exchange.&lt;/p&gt;

&lt;p&gt;Looking at the console logs, &lt;code&gt;executor.py&lt;/code&gt; seemed to be working perfectly. I saw logs like &lt;code&gt;[DRY_RUN] Order placed: ...&lt;/code&gt;. But the Discord notifications, which are supposed to arrive after an order, simply weren't showing up.&lt;/p&gt;

&lt;p&gt;Initially, I thought it might be a Discord issue or just a delay. But after 30 minutes, still nothing. This felt wrong.&lt;/p&gt;

&lt;p&gt;The thought of this happening with real money sent shivers down my spine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  "I thought I placed the order, but it never went through."&lt;/li&gt;
&lt;li&gt;  "I was sure I closed that position, but it's still open."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bugs in notification systems are notorious for creating these kinds of silent failures, and they're genuinely scary.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Investigation: Aha! Found You...
&lt;/h3&gt;

&lt;p&gt;My first step was to isolate the problem. I directly invoked &lt;code&gt;notify.py&lt;/code&gt;, the script responsible for sending notifications. It worked perfectly, sending a test message to Discord. This strongly suggested the issue was upstream, likely within &lt;code&gt;executor.py&lt;/code&gt;, which calls &lt;code&gt;notify.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I took a closer look at &lt;code&gt;executor.py&lt;/code&gt;'s logs. And there it was: the webhook URL, which should have been passed to the notification function, was &lt;code&gt;None&lt;/code&gt;. Bingo.&lt;/p&gt;

&lt;p&gt;But why &lt;code&gt;None&lt;/code&gt;? I store my webhook URL in a &lt;code&gt;.env&lt;/code&gt; file, and other scripts, like &lt;code&gt;planner.py&lt;/code&gt;, were successfully reading it. So I compared the code for &lt;code&gt;planner.py&lt;/code&gt; and &lt;code&gt;executor.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And I immediately spotted the difference. At the beginning of &lt;code&gt;planner.py&lt;/code&gt;, there was a clear &lt;code&gt;load_dotenv()&lt;/code&gt; call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ...
from dotenv import load_dotenv

load_dotenv() # Load environment variables

# ... planner logic ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, &lt;code&gt;executor.py&lt;/code&gt;, the script in question, was missing this &lt;code&gt;load_dotenv()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;This meant that when I ran the entire flow starting from &lt;code&gt;planner.py&lt;/code&gt;, &lt;code&gt;planner.py&lt;/code&gt; would load the &lt;code&gt;.env&lt;/code&gt; variables, making them available to &lt;code&gt;executor.py&lt;/code&gt;. But if I ran &lt;code&gt;executor.py&lt;/code&gt; directly for testing, or if it was called from a different entry point, no one was loading the &lt;code&gt;.env&lt;/code&gt; file. Consequently, the webhook URL was never set, and notifications failed silently.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Resolving Dependencies Where They're Used
&lt;/h3&gt;

&lt;p&gt;Once the cause was clear, the fix was straightforward. I added &lt;code&gt;load_dotenv()&lt;/code&gt; to &lt;code&gt;executor.py&lt;/code&gt; before calling the notification logic.&lt;/p&gt;

&lt;p&gt;Before (simplified):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Calling&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;without&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.notify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;

&lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify_investment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Execution result...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Fails because webhook is not set
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, when the &lt;code&gt;hub&lt;/code&gt; module initializes, &lt;code&gt;os.environ.get('DISCORD_WEBHOOK_INVESTMENT')&lt;/code&gt; returns &lt;code&gt;None&lt;/code&gt;, leading to a silent notification failure.&lt;/p&gt;

&lt;p&gt;After (simplified):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;find_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.notify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;

&lt;span class="c1"&gt;# Find .env file and load environment variables.
# This ensures the webhook URL is set in os.environ.
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DISCORD_WEBHOOK_INVESTMENT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Only load if not already set
&lt;/span&gt;    &lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;find_dotenv&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify_investment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Execution result...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Notification sent successfully
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used &lt;code&gt;find_dotenv()&lt;/code&gt; to ensure that the &lt;code&gt;.env&lt;/code&gt; file is located correctly, regardless of the current working directory during execution. This guarantees that &lt;code&gt;executor.py&lt;/code&gt; can always find and load the webhook URL, no matter how it's invoked.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways and Lessons Learned
&lt;/h3&gt;

&lt;p&gt;This incident taught me three important lessons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DRY_RUN Tests Are God-Tier&lt;/strong&gt;&lt;br&gt;
The value of discovering "normal-looking anomalies" without any financial cost is immense. Things that &lt;em&gt;look&lt;/em&gt; like they're working are the most dangerous. Never skip DRY_RUN tests before production deployment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eliminate "Implicit Assumptions" Between Scripts&lt;/strong&gt;&lt;br&gt;
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 &lt;code&gt;.env&lt;/code&gt;, it's better design to explicitly load them at each entry point or at the beginning of the modules that rely on them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider Assertions for Critical Operations&lt;/strong&gt;&lt;br&gt;
While I caught this with logs, for even more robustness, it might be worth adding an assertion like &lt;code&gt;assert os.environ.get('DISCORD_WEBHOOK_INVESTMENT') is not None&lt;/code&gt; right before critical operations like placing an order or sending a notification. This can catch misconfigurations immediately.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;




&lt;p&gt;Oji / AI Algo Trading Engineer&lt;br&gt;
X: @oji_ai_dev&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>automation</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>My Trading Bot's Silent Killer: How Forgetting to Load `.env` Across Scripts Silenced Discord Notifications</title>
      <dc:creator>oji - building AI in public</dc:creator>
      <pubDate>Wed, 05 Aug 2026 06:25:35 +0000</pubDate>
      <link>https://dev.to/masaoshimadaopen/my-trading-bots-silent-killer-how-forgetting-to-load-env-across-scripts-silenced-discord-2pli</link>
      <guid>https://dev.to/masaoshimadaopen/my-trading-bots-silent-killer-how-forgetting-to-load-env-across-scripts-silenced-discord-2pli</guid>
      <description>&lt;p&gt;Hey everyone, it's your friendly neighborhood dev-dad here. Mid-thirties, full-time engineer by day, battling AI trading bots by night (weekends, really). &lt;/p&gt;

&lt;p&gt;Today, I want to share a subtle but potentially catastrophic bug I found in my bot. Seriously glad I caught this before deploying with real money. The symptom: Discord notifications for order fills just weren't arriving. The culprit: I forgot to load my &lt;code&gt;.env&lt;/code&gt; variables consistently across multiple Python scripts.&lt;/p&gt;

&lt;p&gt;This is a super common pitfall when you're linking several Python scripts in a personal project, and it can be a real headache.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happened: A "Silent Failure" Uncovered by a DRY_RUN
&lt;/h3&gt;

&lt;p&gt;Last weekend, I was running my usual DRY_RUN tests for my FX bot. My bot's logic is split into two main parts: &lt;code&gt;planner.py&lt;/code&gt;, which strategizes trades, and &lt;code&gt;executor.py&lt;/code&gt;, which actually sends orders to the exchange.&lt;/p&gt;

&lt;p&gt;The console logs looked perfectly normal. &lt;code&gt;executor.py&lt;/code&gt; seemed to be doing its job: I saw messages like "[DRY_RUN] Order placed: ...". But the Discord notifications, which &lt;em&gt;should&lt;/em&gt; have been firing, never appeared.&lt;/p&gt;

&lt;p&gt;At first, I thought it was a Discord outage or just a delay. But after 30 minutes, nothing. Something was definitely wrong.&lt;/p&gt;

&lt;p&gt;Thinking about what would have happened if this were real money sent shivers down my spine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  "I thought I placed an order, but it never went through."&lt;/li&gt;
&lt;li&gt;  "I thought I closed a position, but I was still holding it."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bugs in notification systems are terrifying because they create these silent failures. You &lt;em&gt;think&lt;/em&gt; everything is okay, but it's not. This is precisely how real money gets lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Investigation: Unmasking the Culprit
&lt;/h3&gt;

&lt;p&gt;To narrow things down, I first tried calling &lt;code&gt;notify.py&lt;/code&gt; (which handles all notifications) directly. It worked flawlessly; the Discord notification came through. This pointed to an issue within &lt;code&gt;executor.py&lt;/code&gt;, which calls &lt;code&gt;notify.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I re-examined &lt;code&gt;executor.py&lt;/code&gt;'s logs more carefully and immediately saw it: the webhook URL being passed to the notification function was &lt;code&gt;None&lt;/code&gt;. Ah, there it is.&lt;/p&gt;

&lt;p&gt;But why &lt;code&gt;None&lt;/code&gt;? I have the webhook URL stored in my &lt;code&gt;.env&lt;/code&gt; file, and it's loaded correctly when &lt;code&gt;planner.py&lt;/code&gt; executes. &lt;/p&gt;

&lt;p&gt;Comparing &lt;code&gt;planner.py&lt;/code&gt; and &lt;code&gt;executor.py&lt;/code&gt;'s code, the reason became painfully obvious.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;planner.py&lt;/code&gt; correctly includes &lt;code&gt;load_dotenv()&lt;/code&gt; at the top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ...
from dotenv import load_dotenv

load_dotenv() # Load environment variables

# ... planner's logic ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, &lt;code&gt;executor.py&lt;/code&gt;, the problem child, was missing &lt;code&gt;load_dotenv()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This meant that when I ran the full flow (where &lt;code&gt;planner.py&lt;/code&gt; calls &lt;code&gt;executor.py&lt;/code&gt;), &lt;code&gt;planner.py&lt;/code&gt; would load the &lt;code&gt;.env&lt;/code&gt; variables first, so &lt;code&gt;executor.py&lt;/code&gt; &lt;em&gt;appeared&lt;/em&gt; to work. But if I ran &lt;code&gt;executor.py&lt;/code&gt; directly for testing, or if it was called from a different entry point, no one was loading &lt;code&gt;.env&lt;/code&gt;. Consequently, the webhook URL was never set, and notifications silently failed.&lt;/p&gt;

&lt;p&gt;My code was relying on an "implicit assumption" about its execution context. This is the kind of thing that would get flagged in a code review with a team, but in solo dev, it's easy to miss.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Resolve Dependencies Where They're Used
&lt;/h3&gt;

&lt;p&gt;The fix was straightforward once the cause was clear. I added &lt;code&gt;load_dotenv()&lt;/code&gt; to &lt;code&gt;executor.py&lt;/code&gt; before any notification calls.&lt;/p&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Before: Calling notification function without loading .env
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.notify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;

&lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify_investment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Execution result...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Fails because webhook is not set
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, &lt;code&gt;hub&lt;/code&gt; would initialize, and &lt;code&gt;os.environ.get('DISCORD_WEBHOOK_INVESTMENT')&lt;/code&gt; would return &lt;code&gt;None&lt;/code&gt;, leading to a silent failure.&lt;/p&gt;

&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# After: Loading .env before notification
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;find_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.notify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;

&lt;span class="c1"&gt;# Find the .env file and load environment variables
# This ensures the webhook URL is set in os.environ
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DISCORD_WEBHOOK_INVESTMENT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Only load if not already set
&lt;/span&gt;    &lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;find_dotenv&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify_investment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Execution result...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Notification sent successfully
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used &lt;code&gt;find_dotenv()&lt;/code&gt; to ensure that no matter the current working directory, it will always locate the &lt;code&gt;.env&lt;/code&gt; file in the project root. Now, &lt;code&gt;executor.py&lt;/code&gt; will always correctly load the webhook URL, regardless of how it's executed.&lt;/p&gt;

&lt;p&gt;It's a fundamental principle, really: if your code depends on a certain feature (like environment variables), the code &lt;em&gt;using&lt;/em&gt; that feature is responsible for resolving that dependency. A simple truth, but easily overlooked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lessons Learned and Takeaways
&lt;/h3&gt;

&lt;p&gt;I took away three key lessons from this experience:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DRY_RUN Tests are Gold&lt;/strong&gt;&lt;br&gt;
The value of catching "normal-looking anomalies" like this, without any financial impact, is immense. "Seems to be working" is the most dangerous state. Never skip DRY_RUNs before live deployment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eliminate "Implicit Assumptions" Between Scripts&lt;/strong&gt;&lt;br&gt;
When splitting logic across files, it's easy to create implicit assumptions like "that other file must have initialized this." For project-wide settings like &lt;code&gt;.env&lt;/code&gt;, explicitly loading them at each entry point, or at the top of any module that uses them, is a much more robust design.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider Assertions for Critical Operations&lt;/strong&gt;&lt;br&gt;
While logs helped me catch this, for even greater robustness, adding an assertion right before critical operations like sending an order or a notification could be beneficial. Something like &lt;code&gt;assert os.environ.get('DISCORD_WEBHOOK_INVESTMENT') is not None&lt;/code&gt; would immediately flag misconfigurations. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Operating a personal bot means constantly battling these subtle bugs. But each one you squash makes the system stronger. Another weekend, another step towards a smarter bot.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>automation</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
