The hallucinated API
AI models confidently call methods and functions that do not exist. They pattern-match a plausible name from a similar language or a similar API and present it with total fluency. Rust has str::strip_prefix, so an AI will happily write s.strip_prefix("DEBUG: ") in Python — where there is no such method.
The tell is mechanical and immediate: run it and Python raises AttributeError ('str' object has no attribute 'strip_prefix') or NameError/TypeError. A hallucinated API doesn't fail subtly — it fails the moment that line executes. The danger is only when you *don't* run it and trust the surrounding logic on faith.
The fix is to find the real API. Python's actual string methods for this are removeprefix(prefix) and removesuffix(suffix) (added in 3.9). Both return the string unchanged if the affix isn't present, so no if guard is needed.
When AI code calls a method you don't recognise, the reflex is: *does this exist?* — check dir(obj), the docs, or just run it. Don't reason about the logic of a method that was never real.
Syntax
# AI wrote these — they DO NOT EXIST in Python:
s.strip_prefix("DEBUG: ") # AttributeError (this is Rust, not Python)
s.chop_suffix("\n") # AttributeError (invented name)
# The REAL Python 3.9+ API:
s.removeprefix("DEBUG: ") # -> "started up"
s.removesuffix("\n") # -> drops a trailing newline if present
# Spot-check whether a method is real:
hasattr(str, "removeprefix") # True
hasattr(str, "strip_prefix") # FalseWorked examples
The hallucinated methods raise AttributeError when run
s = 'DEBUG: started up'
try:
s.strip_prefix('DEBUG: ') # AI invented this
except AttributeError as e:
print(e)
# Output:
# 'str' object has no attribute 'strip_prefix'The real API — removeprefix / removesuffix
print('DEBUG: started up'.removeprefix('DEBUG: ')) # started up
print('ok\n'.removesuffix('\n')) # ok
# No-op when the affix isn't there (no guard needed):
print('plain'.removeprefix('DEBUG: ')) # plainSwapping the hallucinated calls for the real ones
def clean_line(s):
s = s.removeprefix('DEBUG: ') # was the fake strip_prefix
s = s.removesuffix('\n') # was the fake chop_suffix
return s.strip()
print(repr(clean_line('DEBUG: ok\n'))) # 'ok'
print(repr(clean_line(' plain '))) # 'plain'
# Output:
# 'ok'
# 'plain'Common mistakes & gotchas
Trusting a method name because it sounds right
strip_prefix, chop_suffix, list.add, dict.has_key — all read like real Python and none exist (the real ones are removeprefix, removesuffix, list.append, key in dict). Plausibility is exactly what the model is good at; existence is what you have to check.
Catching the AttributeError instead of fixing it
Wrapping a hallucinated call in try/except AttributeError makes the crash disappear but the feature still does nothing. An AttributeError means the API is wrong — replace the call, don't swallow it.
Assuming cross-language methods carry over
Models blend languages. strip_prefix is Rust, substring is JavaScript/Java, len(arr) not arr.length. When AI writes Python that feels like another language you know, that's the moment to verify the method against Python's actual API.
Why it matters
Hallucinated APIs are the most common single defect in AI code, and the easiest to catch — *if you run it*. A reviewer who reflexively checks whether a method exists turns a confident lie into a one-line fix; one who trusts the prose ships code that can't even import.