To catch an API an AI coding assistant made up, run the type checker and linter, then check every unfamiliar library call against the definition in the version your lockfile installs, not against memory or the latest docs. Pay extra attention to options passed as plain objects, because an unknown key usually fails silently.
Made-up APIs are easy to miss because they look exactly like real ones. The rest of this post shows what they look like, the checks that find them, and what a review tool can and can't do about them.
What does a made-up API look like?
A common one in Node:
import { promises as fs } from 'node:fs'
if (await fs.exists(configPath)) {
// ...
}
There is no fs.promises.exists. The callback module has fs.exists, which is deprecated, and the promise API never had one. The name fits the pattern of the real API so well that it reads as correct.
Other shapes of the same mistake:
- A function from a different version of the library, added later or removed earlier.
- A real function with the wrong arguments, or arguments in the wrong order.
- An option that sounds right, such as
retrieson a client that doesn't support it. The call works, the option is ignored, and the code reads as if it retries. - A method from a similar library, such as a lodash name used on a native array.
Which checks catch them?
Run the type checker and the linter
In TypeScript, tsc --noEmit rejects fs.promises.exists outright, because the property doesn't exist on the type. That catches the obvious cases in seconds. In plain JavaScript or Python, nothing fails until that line runs, which may be only on the branch nobody tested. A type checker such as mypy or Pyright helps there when the library ships types.
Check the definition in your installed version
For any call you don't recognise, jump to its definition in your editor. Go-to-definition lands in the installed package's types or source, which is the version your lockfile pinned. A library's website usually documents the latest release, which may not be the one you run.
Treat options objects with suspicion
Unknown keys in an options object rarely cause an error. TypeScript flags an unknown key only when you pass an object literal straight to a typed parameter. Build the object first, or type it loosely, and the extra key passes. For each option in the diff, find it in the library's type definition or source.
Make the call run
A test that runs the code path catches a missing function at once. If the pull request adds a call with no test that reaches it, ask for one, or run it locally. A failing test is the plainest evidence there is.
Ask why this library
If the request was "read the config file", a new dependency or an unfamiliar method is worth a question. Assistants sometimes reach for an API they half remember when the standard library already does the job.
How does Hyperpowers help?
Hyperpowers is a free VS Code extension that explains a pull request change by change. It helps you find the calls worth checking. It doesn't prove that an API exists.
- The why next to each change. Each change comes with what changed and why. When the code was written with Claude Code on the machine that created the walkthrough, the why comes from the request in that session. A call that doesn't fit the request stands out.
- Reading in the order the code runs. The review goes database, backend, frontend, then tests. You meet the code that defines data before the code that calls it, so a call to something that was never defined is easier to notice.
- The real file around each change. The change opens in the editor, so go-to-definition and find-references work on the call right there.
- Ask Claude about this change. Type "Does
fs.promiseshave anexistsmethod?" under the change, and Claude answers in a few sentences. - Review with Claude. For backend code it looks at input validation, permissions, error handling and data that stays correct, and drafts a comment for each thing worth raising. You decide what gets posted.
What can't it do?
Hyperpowers never runs code from the repository, and it doesn't run your type checker or tests. Claude's answers and review read the change, its diff and the notes. They don't look inside your installed packages, so Claude can be wrong about an API in the same way the assistant that wrote the code was. Use it to decide where to look, then confirm with the type checker, the definition and a test.
Try it
Try Hyperpowers in your browser on an example pull request, or install the extension. For the other mistakes to look for in generated code, see Reviewing code an AI wrote: what to check.
Common questions
Why do AI assistants make up APIs?
A model writes code that fits the patterns it learned. A name that fits the pattern of a real API can be produced even when that function doesn't exist in your version.
Does TypeScript catch every made-up API?
No. It catches calls to functions that don't exist on a typed object. It can miss unknown options that aren't object literals, calls through any, and libraries without type definitions.
Can a bot reviewer catch them?
Sometimes. A model reviewing the diff can flag a call it believes is wrong, and it can also miss one or flag a real API by mistake. The type checker and a test are the reliable checks.