For about four days, a calculator I built was telling people that one RTX 4090 could make $171.31 a day mining Ergo.
That worked out to around $5,101 a month, with a $1,799 graphics card supposedly paying for itself in 11 days.
Yeah. That was very wrong.
The real result with the same settings was closer to 18 cents a day in revenue and about a $1.12 loss per day after electricity.
Break-even wasn't 11 days.
It was never.
I wanted to write this up because I'm not a professional developer. I'm probably closer to what people now call a vibe coder. I know enough to build things, troubleshoot them, change code, use AI to help me, and usually figure out why something isn't working.
But I'm still learning as I go.
And this was one of those bugs where everything looked completely reasonable until I stopped and said:
There is absolutely no way this number is real.
What the calculator was showing
If you loaded the page and didn't change anything, you'd see something like this:
Daily revenue $171.31
Daily profit +$170.02 Profitable ✅
Monthly +$5,101
Break-even 11 days
Even worse, basically every coin in the comparison table looked profitable.
They weren't.
Anyone who knows GPU mining would probably spot the problem immediately.
If you could really buy an RTX 4090 for around $1,800 and recover the cost in 11 days, people would be buying every 4090 they could find.
But the whole reason I built a calculator like this is for people who don't already know the answer.
If you're researching whether mining is worth trying, you might look at that number and think:
Wow, I didn't realize GPU mining was still this profitable.
That's where a bad calculator becomes more than just a funny bug.
Someone could actually make a purchasing decision based on it.
So what went wrong?
Part of the site uses automatically updated mining data.
The data included a value like this:
{
"symbol": "ERG",
"algorithm": "Autolykos2",
"rev_per_th_usd": 1310.945239
}
The important part is the unit.
That number was based on terahashes per second, or TH/s.
Elsewhere, the calculator was doing this:
const revPerTh = parseFloat(coinOpt.dataset.rev);
const totalHash = hashrate * count / 1000; // MH/s -> GH/s
const grossRev = totalHash * revPerTh;
I had one value in GH/s and another value based on TH/s.
Those aren't the same thing.
There's a factor of 1,000 between them.
Once I understood that, the crazy result suddenly made perfect sense.
For example:
132 MH/s = 0.132 GH/s
0.132 × 1310.945 = $173.04
After the pool fee = $171.31
That matched exactly what the site was showing.
So the calculator wasn't randomly broken.
It was very confidently doing the wrong math because I had given it two values using different units.
This is the part that surprised me
Nothing looked obviously broken.
The data file was loading.
The numbers were valid.
The calculator was doing multiplication correctly.
The page wasn't throwing errors.
From the browser's point of view, everything was working.
That's probably one of the bigger lessons for me from building things with AI.
AI can help you write code that runs.
It can help fix syntax errors.
It can help explain functions.
It can even help build a pretty complicated tool.
But code running successfully doesn't mean the answer makes sense.
In this case, the most useful debugging tool ended up being common sense.
An RTX 4090 does not make $5,000 a month mining Ergo.
Once I accepted that the output itself had to be wrong, it became much easier to work backward and find out why.
One comment actually made me ignore the problem
The page loaded the live mining data using code like this:
// fails silently if unavailable
fetch('/mining/mining-data.json')
.then(r => r.json())
.then(applyLiveCoins)
.catch(() => {});
I had looked at that comment multiple times.
In my head, I read it as:
If the live data doesn't work, no big deal. The page has fallback values.
So I more or less stopped paying attention to that section.
Except the live data wasn't failing.
It was loading correctly every time.
And every time it loaded, it was replacing the reasonable fallback numbers with the bad ones.
So the part I had mentally categorized as harmless was actually the thing causing the problem.
My first fix wasn't really enough
My first reaction was basically:
Fine. Make the variable names more obvious.
Instead of something like:
revPerTh
use something that spells the unit out.
That's definitely better.
But then I realized something.
The bad number was so ridiculous that the site probably should have rejected it regardless of how the mistake happened.
So I added what is basically a sanity check:
const REV_SANITY_MIN = 0.0001;
const REV_SANITY_MAX = 100;
const usable = rows.filter(c => {
const v = Number(c.usd_per_ghs_day);
return (
isFinite(v) &&
v >= REV_SANITY_MIN &&
v <= REV_SANITY_MAX &&
c.symbol
);
});
if (!usable.length) return;
I'm not trying to say the value has to be perfectly accurate.
I'm just saying:
If this number is completely outside the range of anything believable, don't automatically publish it.
And if the live data looks suspicious, the page keeps the older known-good numbers instead.
I'd rather show slightly outdated numbers than confidently tell someone their GPU is going to print $5,000 a month.
Then I started noticing the same kind of problem everywhere
Once I started looking for numbers that were technically valid but obviously wrong, I found more of them.
| What I saw | What was actually happening |
|---|---|
| Used RTX 4090 for $171.68 | The scraper grabbed a cable instead of a GPU |
| RTX 3090 for $2,399 | The search also matched an RTX 3090 Ti |
| Insane mining revenue numbers | The reference hardware was an ASIC, not a GPU |
| $5,101/month from one RTX 4090 | GH/s and TH/s got mixed together |
The funny part is that none of these were really complicated programming mistakes.
The code was doing what I told it to do.
The problem was that what I told it to do didn't match reality.
I even managed to create basically the same bug while fixing another one.
I was trying to filter RTX 3090 Ti cards out of RTX 3090 results.
So I checked whether the listing contained:
ti
That seemed reasonable.
Until I realized a perfectly valid listing said:
Founders Edition
Which also contains:
ti
So my fix for bad matching was itself doing bad matching.
That one made me laugh once I figured it out.
Sanity checks can be wrong too
There's another side to this.
You have to be careful not to assume that every surprising number is bad data.
I ran into that while working on another GPU tool for local AI performance.
I expected cards with higher memory bandwidth to generally perform better.
Then I had an RTX 3090 with around 936 GB/s of bandwidth showing worse results than a 4070 Ti Super with around 672 GB/s.
My first reaction was:
The benchmark must be wrong.
Except it wasn't.
The newer architecture was simply using its available bandwidth more efficiently.
So now I'm trying to treat these sanity checks as warnings, not corrections.
The system should basically say:
This looks strange. Check it.
Not:
This is definitely wrong, so I'm going to change it automatically.
That distinction matters.
Otherwise I'm just replacing one bad assumption with another one.
What I learned from it
The main thing I'm changing in how I build these tools is pretty simple.
Whenever I'm showing a calculated number to someone, especially something involving money, I want to ask:
Does this result pass a basic reality check?
Not just:
- Did the code run?
- Did the JSON load?
- Is this a valid number?
- Did the formula execute?
But:
Could this number actually make sense in the real world?
I'm still going to use AI heavily to build things.
That's part of what makes projects like StashGrid possible for me.
But this was a good reminder that AI-generated code, APIs, automated feeds, tests, and working JavaScript still need a human somewhere in the loop asking:
Wait...does that actually make sense?
In this case, the answer was definitely no.
The calculator that caused all of this is the GPU Mining Calculator on StashGrid.
The numbers are a lot less exciting now.
Which is probably a good sign.
Top comments (0)