Skip to main content
友田 陽大
Running the app you built with AI
バイブコーディング
AI駆動開発
型安全
個人開発
テスト

"It runs, but it's wrong" — the quietest and most common AI-generated bug

The most common defect in AI-written code isn't a vulnerability — it's a result that is simply wrong while nothing errors. Totals that don't add up, search results that drop rows, failures reported as successes: how they happen, and how to find them without reading code.

Published
Reading time
9 min read
Author
友田 陽大
Share

We've been talking about security, but in fact the most common defect in AI-built apps is not a vulnerability.

No error is raised, and the result is simply wrong. That's it.

What makes this kind of bug awkward is that there is almost no opportunity to discover it. The screen looks normal. Nothing errors. Nothing lands in the logs. A number is just slightly off. So it goes unnoticed for months — sometimes forever.


1. Why AI produces these

AI is extremely good at writing the path where things go well.

Ask it to "show a list of the user's orders" and it writes code that works perfectly for a user who has orders, with valid data, accessed by one person at a time.

What it doesn't write is the cases below:

  • There are zero orders
  • The date sits exactly on a boundary (23:59:59 on the last day of the month)
  • Two people act at once on the same record
  • An external service is slow or down
  • A number is negative or absurdly large
  • A string contains emoji or unusual characters

These are called abnormal conditions. And — abnormal conditions are exactly what happens in production.

The reason is straightforward: they weren't in the instruction. AI isn't being careless; you didn't say "when there are zero orders, display 'no orders yet'." Of course you didn't. Only someone who has been burned by it once thinks of that.


2. Five recurring patterns

Here are the shapes I actually see. All of them look normal on screen.

Pattern 1: swallowed exceptions

The most common, and the most dangerous.

Code catches a failure and then does nothing. The error reaches neither the screen nor any log, and processing continues as though nothing happened.

[what you get]
- "Saved!" when nothing was saved
- a completion screen when no email was sent
- an order confirmed when the payment failed

AI writes this because it is trying to stop errors from halting execution. Tell it "an error appears" and it will make the error stop appearing — and sometimes that takes the form of ignoring the error.

How to check: make it fail on purpose. Cut the network, leave a required field empty, enter an absurdly long string. If it still says "success," something is being swallowed.

Pattern 2: date boundaries

In aggregation or filtering, the boundary day (or second) is off by one.

[what you get]
- a monthly total omits the last day, or includes the first of the next month
- "today's orders" misses orders placed around midnight
- a timezone shift makes Japanese morning count as the previous day

The nine-hour gap between Japan time and UTC is a place AI gets wrong especially often. It looks right when you test it, and drifts only during late-night hours.

How to check: create one record at the end of a month and one at the start, and confirm both land in the correct month. Try records around midnight too for extra confidence.

Pattern 3: non-deterministic ordering in pagination

If a list shows "20 at a time" and the order isn't specified, entries drop or duplicate on page two.

A database considers itself free to return rows in any order when none is requested. Getting a different order on page one and page two genuinely happens. PostgreSQL's own documentation states that a LIMIT without ORDER BY yields an unpredictable row order.

[what you get]
- paging through the list, some entries never appear
- the same entry appears on two pages
- fine while data is sparse, suddenly wrong once it grows

That it only surfaces once data grows makes this particularly nasty.

How to check: enter about 30 records and compare pages one and two. Confirm the total is 30 with no duplicates.

Pattern 4: rounding drift

In money or percentage calculations, the handling below the decimal point slips.

[what you get]
- the line-item sum and the displayed total differ by one unit
- tax-inclusive → tax-exclusive → tax-inclusive doesn't round-trip
- applying a discount makes the total go negative

Even a one-unit difference is a problem in accounting. The standard practice is to hold money as integers in the smallest unit rather than as decimals, but AI will use decimals unless told otherwise.

How to check: try amounts that produce fractions, and compare the total on screen against adding the line items yourself.

Pattern 5: ignored partial failures

When several operations are performed together, a failure partway through doesn't stop the rest.

[what you get]
- the order was created but stock wasn't decremented
- the user was deleted but their data remains
- the payment completed but no order record was created

You need a mechanism that guarantees "all succeed or all fail" (a transaction), and that too has to be asked for.

How to check: hard to spot by eye. Use the instruction in the next section and have an AI investigate.


3. How to find them — what you can do without reading code

There is one principle:

Compute the right answer by another route and compare

Whether the number on screen is correct cannot be determined by looking at the screen. You need an independent check.

Method 1: hand-calculate with very little data

This is the most reliable.

With only three to five records entered, compare the on-screen aggregate against your own arithmetic. With so few records you can check it in your head.

Most people try to test by entering lots of realistic-looking data — but then you can't verify anything. Deliberately keeping it small is the trick.

Method 2: aim at the boundaries

Try the edges, not comfortable middle values.

  • Zero records
  • Exactly one record
  • End of month / start of month, around midnight
  • Amount zero, negative
  • A name that is one character, only emoji, very long

AI doesn't get middle values wrong. It gets edges wrong.

Method 3: make it fail on purpose

  • Close the browser mid-operation
  • Cut the connection and submit
  • Press the same button twice quickly
  • Do the same operation simultaneously in another tab

"Press the same button twice" is especially effective and exposes duplicate registration or double submission immediately.


4. The fix — write down what must never break, first

This is the heart of it.

Most people ask an AI to "write tests." That's fine as far as it goes, but AI writes tests against the implementation it produced. If the implementation is wrong, the test encodes the same mistake. The test passes and the bug remains.

What works is reversing the order.

What you write

You can't write code, but you can state, in plain language, the conditions that must always hold. In fact you're the only one who can — you're the one who knows what the app is supposed to do.

Examples:

- an order's total always equals the sum of its line items
- running the same search twice returns the same rows in the same order
- paging through every page yields every record, with no duplicates or gaps
- a balance is never negative
- deleting a user leaves none of that user's data behind
- a monthly total covers 00:00:00 on the first through 23:59:59 on the last (JST)
- if payment fails, no order is created
- if saving fails, an error is always shown on screen

Write these first, then ask the AI to "turn these into tests and check whether the implementation satisfies them."

Where it doesn't, the implementation is what gets fixed. In that order, the AI cannot justify its own implementation.


5. Instructions to paste into your AI tool

Investigate the current state

Read this app's entire codebase and list places that are problematic on the
following axes, as a table. Do not fix anything yet.

(1) Places where an exception is caught and nothing is done (swallowed) — where
    the failure reaches neither the user nor any record
(2) Places where date/time handling looks doubtful, especially timezone
    conversion and whether month start/end are inclusive
(3) List queries with no explicit ordering (ORDER BY), particularly paginated ones
(4) Money or percentage calculations using decimals, or where the rounding
    direction is unspecified
(5) Places that perform several updates together without a transaction
(6) Places with no branch for zero or one records

For each, explain in plain language under what conditions it goes wrong and how
it would look wrong on screen. I cannot read code.

Turn your conditions into tests

Below are conditions that must always hold in this app. Write them as tests and
check whether the implementation actually satisfies them. Where something is not
satisfied, fix the implementation rather than the test.

- (list the conditions you wrote out here)

Tests must include boundary values: zero records, one record, end of month,
midnight, amount zero and negative. When a test fails, explain in plain language
which condition failed and which part of the implementation caused it.

6. Don't believe "I fixed it"

One last habit, the most important one in this area.

AI reports "fixed." Usually it genuinely did. But believing it without checking is especially dangerous for this class of bug — since nothing errors, nothing happens even when the fix didn't land.

After a fix, check it the same way you found it.

  • Compare against hand arithmetic with very little data
  • Try the boundaries (end of month, zero records, one record)
  • Make it fail on purpose

Two or three minutes. Whether you have this habit is the difference between an app that is quietly broken after launch and one that isn't.


Summary

  • The most common defect in AI-generated code isn't a vulnerability — it's a wrong result with no error
  • AI is excellent at the happy path and writes nothing for abnormal conditions unless told to. Production is abnormal conditions
  • Five recurring patterns: swallowed exceptions, date boundaries, non-deterministic pagination, rounding drift, ignored partial failures
  • To find them, compute the answer another way: little data plus hand arithmetic, aim at boundaries, make it fail on purpose
  • To prevent them, write the conditions that must never break in plain language first, and have those turned into tests. You can state conditions without reading code
  • "The AI said it fixed it" is not confirmation. Re-check the same way

Security holes only cause harm if someone attacks; this class of bug happens on its own, guaranteed. In priority terms, the realistic order is to close the four pre-launch items and then come here.

Frequently asked questions

What does 'no error but wrong' actually look like?
The program runs to completion, no error appears anywhere on screen, and yet the calculated result or displayed content is incorrect. If a sales total is missing the last day of the month, the figure still renders neatly, so you cannot tell it is wrong without knowing the right answer. Bugs that raise errors get found; this kind sits there for months.
Why is AI prone to producing these?
Because AI is extremely good at writing the happy path and does not account for abnormal conditions unless told to. Empty data, a date exactly on a boundary, two people acting at once, a slow external service — none of these are implemented if they weren't in the instruction. And those conditions are exactly what occurs in production.
Can I find them without reading code?
To a useful extent, yes. The effective technique is computing the right answer by another route and comparing. For a sales total, add the line items yourself and compare against the figure on screen. If they disagree, one of them is wrong. Entering only a handful of records and comparing against mental arithmetic is the most reliable check, and anyone can do it.
Does writing tests prevent this?
It does, though asking an AI to write tests is sometimes not enough on its own. AI writes tests against the implementation it produced, so if the implementation is wrong the test encodes the same mistake. What works is the reverse order: you state in plain language the conditions that must always hold, and have those turned into tests.
What is a swallowed exception?
It is code that catches a failure and then does nothing with it. The error reaches neither the screen nor any log, and processing continues as though nothing happened. The result is 'Saved!' when nothing was saved, or a completion screen when no email was sent. AI tends to write this shape while trying to stop errors from halting execution.

References

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

“It works. But is it safe to launch?”

Twenty questions, no signup — a pre-launch self-check for the app you built with AI

You don't need to read any code. Answer yes / no / not sure to questions like “can only the person who logged in see their own data?” You get your risks ordered by severity, plus a fix instruction you can paste straight into Claude Code or Cursor. Nothing you type leaves your browser.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

Also worth reading