ai-coding-minesIndexGitHub

Five ways a success response lies

Write APIs

Hit all five in one day, so it became a table.

ResponseWhat actually happened
200 + code=ERRORTried to modify a resource under review. HTTP is 200.
200 + rows=0Filtered on an enum value that doesn't exist. Not an error; an empty result.
200 + code=SUCCESS + no effectPartial update silently ignored. 26 minutes later, unchanged.
200 + code=SUCCESS + warningA warning attached, but it actually applied. Read the warning as failure and you retry healthy items.
400 PRECONDITION_FAILEDSimply a path that doesn't exist. Not a precondition violation.

There are at least three axes of success/failure: HTTP status, code in the body, and the actual value on re-fetch. The first two can both pass while the third differs.

Enforcement

def ok(code, resp):
    return code == 200 and isinstance(resp, dict) and resp.get("code") != "ERROR"

Without it, ~700 items spun for nothing. All rejected, all recorded as success in the progress file.

And this is still not enough. Row 3 in the table passes ok(). After every write, re-fetch the single record and check the real value. If there's a change-history endpoint, that is even more reliable.

The reverse direction: a success that looks like failure

A write's success response carried message as the string "[]". Not an empty array; a truthy string that looks like one. Code that judged errors with if msg: recorded items that had applied correctly as failures. Empty-value representations vary by type: "", [], "[]", {}, null. Judge by content, not by presence.

A contaminated failure list invalidates every diagnosis built on it. Those "failures" became the evidence for a wrong root cause; the real culprit was elsewhere. When one verdict function is wrong, throw away not just the batch result but every conclusion drawn from it.

A sixth shape: the rejected list went unread

A tracking-registration API returns accepted and rejected as separate lists. The wrapper ignored the rejected list and recorded every item as registered in the local DB. Items rejected because carrier auto-detection failed sat there untrackable. Count accepted, and alert when it is 0.

And accepted isn't the end either. Registration can succeed while tracking returns not-found. "Accepted" means registered, not tracked. Success has one more layer.