DEV Community

Superwavvy
Superwavvy

Posted on

5 Errors I Hit Building DeFi Bots (And How to Fix Them)

Building production bots on free APIs sounds cool in theory. In practice, you hit walls immediately. Here are the 5 real errors I encountered while building two Ethereum monitoring bots, and exactly how I fixed them.

Error 1: Alchemy Event Listeners Timeout After 5 Minutes

The Problem:
I started monitoring Aave liquidations using ethers.js event listeners on free-tier Alchemy.

provider.on(filter, (log) => {
  console.log("Liquidation detected:", log);
});
Enter fullscreen mode Exit fullscreen mode

Worked perfectly for 5 minutes. Then the WebSocket died. No error message. Just silence. Listener stopped working forever.

Why it happens:
Free-tier Alchemy (and most providers) have timeout limits on WebSocket connections. Idle connections get dropped. No reconnect logic on the free tier.

The Fix:
Stop using event listeners. Use polling instead.

async function pollLiquidations() {
  const currentBlock = await provider.getBlockNumber();
  const logs = await provider.getLogs({
    address: AAVE_LENDING_POOL,
    topics: [LIQUIDATION_CALL_TOPIC],
    fromBlock: currentBlock - 9,
    toBlock: currentBlock
  });

  logs.forEach(log => handleLiquidation(log));
}

// Poll every 15 minutes
setInterval(pollLiquidations, 15 * 60 * 1000);
Enter fullscreen mode Exit fullscreen mode

The lesson: On free tier, reliability > real-time. Polling every 15 minutes that works beats real-time listeners that disconnect.


Error 2: CoinGecko Rate Limit 429 (Too Many Requests)

The Problem:
I wanted to track 5 tokens: UNI, AAVE, USDC, DAI, USDT.

const tokens = ['UNI', 'AAVE', 'USDC', 'DAI', 'USDT'];

async function getPrices() {
  const prices = await Promise.all(
    tokens.map(token => 
      axios.get(`https://api.coingecko.com/api/v3/simple/price?ids=${token}...`)
    )
  );
}

// Check every 15 minutes
setInterval(getPrices, 15 * 60 * 1000);
Enter fullscreen mode Exit fullscreen mode

After a day, I got slammed with 429 errors. CoinGecko rate-limited me. Price alerts stopped working.

Why it happens:
Free-tier CoinGecko allows ~5 requests per second, but daily limits kick in after 50 concurrent calls per minute. 5 tokens × 96 checks/day = 480 calls. You hit the limit.

The Fix:
Reduce frequency OR reduce tokens. I chose frequency.

const tokens = ['UNI', 'AAVE']; // 2 tokens only

// Check every 2 hours (not 15 mins)
// 2 tokens × 12 checks/day = 24 calls. Under limit.
setInterval(getPrices, 2 * 60 * 60 * 1000);
Enter fullscreen mode Exit fullscreen mode

Still catches all meaningful moves (5%+ happens in hours, not minutes).

The lesson: APIs are precious on free tier. Reduce scope, not reliability. 2 tokens checked reliably > 5 tokens checked intermittently.


Error 3: Supabase RLS "New Row Violates Row-Level Security Policy"

The Problem:
Bots ran fine for 2 days. Then suddenly:

Supabase error: new row violates row-level security policy for table "price_history"
Enter fullscreen mode Exit fullscreen mode

Both bots stopped writing data. Data collection halted. Silent failure.

Why it happens:
I had Row-Level Security (RLS) enabled but forgot to disable it for anonymous (public) access. When the bots tried to INSERT with anon key, RLS rejected them.

// This would fail
const { error } = await supabase
  .from('price_history')
  .insert([{ symbol: 'UNI', price: 5.94 }])
Enter fullscreen mode Exit fullscreen mode

The Fix:
Disable RLS on the tables (if you're the only user):

ALTER TABLE price_history DISABLE ROW LEVEL SECURITY;
ALTER TABLE liquidations DISABLE ROW LEVEL SECURITY;
Enter fullscreen mode Exit fullscreen mode

Or enable RLS but create a policy:

CREATE POLICY "Enable insert for all" ON price_history
  FOR INSERT WITH CHECK (true);
Enter fullscreen mode Exit fullscreen mode

The lesson: RLS is security theater on hobby projects. Disable it for free tier. Enable it when you have real users.


Error 4: "Cannot Find Module" In Termux File Creation

The Problem:
I created a data analysis script but it wouldn't run:

$ node data-analysis.js

Error: Cannot find module '/data/data/com.termux/files/home/data-analysis.js'
Enter fullscreen mode Exit fullscreen mode

File seemed to exist, but Node couldn't find it. Turned out the file never actually created properly.

Why it happens:
When copying files to Termux , file paths get weird. The tool thinks it created the file, but Termux didn't actually receive it.

The Fix:
Create files directly in Termux using nano:

nano data-analysis.js
Enter fullscreen mode Exit fullscreen mode

Paste content, save with Ctrl+X → Y → Enter.

Verify with:

ls ~/*.js
Enter fullscreen mode Exit fullscreen mode

The lesson: Don't rely on external file creation tools for Termux. Nano is slower but reliable.


Error 5: Can't Exit tmux On Mobile Keyboard

The Problem:
I attach to a tmux session to check bot output:

tmux attach -t price-alert
Enter fullscreen mode Exit fullscreen mode

See the output, want to exit. Try Ctrl+B then D. Nothing happens. Keyboard doesn't register the key combo properly on mobile.

Stuck in the session. No escape.

Why it happens:
Mobile on-screen keyboards don't register modifier key combos well (Ctrl+B, Alt+X, etc). Long-press + tap doesn't work reliably.

The Fix:
Don't attach at all. Use capture-pane instead:

tmux capture-pane -t price-alert -p
Enter fullscreen mode Exit fullscreen mode

Shows last output without entering the session. No exit needed. No stuck state.

For killing a session if you DO get stuck:

# In a new terminal
tmux kill-session -t price-alert
Enter fullscreen mode Exit fullscreen mode

The lesson: Avoid interactive sessions on mobile. Use read-only commands instead.


The Pattern

All 5 errors follow the same theme:

Free tier + unconventional setup (mobile, no servers) = constraints.

The fix isn't "pay more" or "use better tools." It's work within constraints:

  • Event listeners die → use polling
  • Rate limits hit → reduce scope
  • RLS blocks → disable it
  • File creation fails → use native tools
  • Keyboard combos don't work → avoid them

That's the real lesson. Not the specific fixes, but the mindset: I'm not building for ideal conditions. I'm building for free APIs, free databases, and a phone running Linux.

Ship anyway.


Running on: Termux (Android), free-tier Alchemy, free-tier CoinGecko, Supabase free tier, tmux

Timeline: Sept 1-12, 2026. Two weeks into production.

Top comments (1)

Collapse
 
raknaos profile image
Raknaos

The polling-over-listeners conclusion is right on free tiers, but the failure mode to watch for is that a dropped listener, a silent throttle and 'nothing happened today' all look identical in the logs. We run the same shape on a VPS with one addition: a 'last successful poll' gauge that alerts when it goes stale, instead of trusting that a missing row means a missing event.

On RLS I'd push back slightly. What actually bit you was a policy change landing with no write test behind it, and RLS was the only thing that surfaced it. Disabling it makes the insert work and removes your one signal. Cheaper trade: keep RLS, add the INSERT policy, and put a canary write in the startup path so policy drift fails loudly at boot rather than quietly two days later.