Your Lambda List Was Silently Truncated at 200 — And Your AI Assistant Never Knew

작성자

카테고리:

← 피드로
DEV Community · Siddharth Pandey · 2026-07-21 개발(SW)
Cover image for Your Lambda List Was Silently Truncated at 200 — And Your AI Assistant Never Knew

Siddharth Pandey

Hook

An AWS account with 240 Lambda functions runs infrawise analyze. The tool prints a clean summary: services detected, findings generated, no errors. A developer asks their AI assistant, wired up through MCP, “does this function have a dead-letter queue?” for a function that happens to be function #217 in the account. The assistant calls get_lambda_overview, gets back a list, doesn’t find the function, and confidently tells the developer it doesn’t exist — or worse, silently skips it and reasons about a different function with a similar name. No error. No warning. Just a wrong answer delivered with total confidence, because 40 functions never made it into the graph in the first place.

That was Infrawise issue #40, and it’s a useful case study in how a tool whose entire pitch is “stop AI assistants from guessing” can quietly start guessing itself.

The 200-function wall

Infrawise builds an in-memory graph of a project’s infrastructure — tables, functions, queues, indexes — and exposes it to AI coding assistants through 21 MCP tools. extractLambdaMetadata in src/adapters/aws/services.ts is the function responsible for pulling every Lambda function into that graph. It calls AWS’s ListFunctionsCommand in pages of 50 and loops until AWS says there’s nothing left:

do {
  const res = await client.send(new ListFunctionsCommand({ Marker: marker, MaxItems: 50 }));
  // ...push each function into the array...
  marker = res.NextMarker;
} while (marker && functions.length < 200);

Enter fullscreen mode Exit fullscreen mode

That trailing && functions.length < 200 is the whole bug. Once the running total hit 200 — four pages in — the loop stopped, even though AWS was still handing back a NextMarker and had more functions to give. There was no error, no thrown exception, no log line. The function just returned early with a partial list and reported success.

For a small project this never surfaces. Most side projects don’t have 200 Lambda functions. But “common in larger orgs,” as the issue itself puts it, is exactly the audience infrawise is trying to win — teams with enough infrastructure that pasting schemas into a prompt every session actually hurts. Those are the accounts most likely to hit the cap, and the ones with the least tolerance for a tool that quietly drops data.

Why silent is worse than wrong

Infrawise’s own docs describe two pillars: Context — give the AI assistant your real schema instead of making the developer paste it — and Guard — catch expensive infrastructure mistakes before they ship. The 200-function cap broke both, and it broke them without telling anyone.

Every function past the cap disappeared from the graph entirely — no node, no edges, nothing for the graph engine to attach event-source mappings, IAM roles, or trigger metadata to. Three consumer paths inherited that gap directly:

  • LambdaMissingTriggerDLQAnalyzer — the analyzer that flags Lambda triggers with no dead-letter queue — silently produced zero findings for those functions. Not “skipped, see warning.” Zero findings, same as a function that’s perfectly configured.
  • analyze_function, the MCP tool an AI assistant calls before writing or reviewing a handler, would report no issues for a function it never saw, rather than saying it didn’t have data.
  • get_lambda_overview, the tool that lists every function’s runtime, memory, timeout, and triggers, just wouldn’t include the function in the list at all.

None of these paths distinguish “checked and found nothing wrong” from “never checked.” That distinction is the entire value proposition of a deterministic tool. Infrawise’s pitch, explicit in its own docs, is that it doesn’t use an LLM to analyze infrastructure — everything is AST parsing, schema introspection, and rule-based analyzers, specifically so an AI assistant gets ground truth instead of a guess. A silent truncation at 200 functions turns that ground truth into a guess anyway, just one dressed up as certainty.

A pattern, not a one-off

The 200-function cap wasn’t an isolated mistake — it’s one of several bugs in Infrawise’s own issue tracker that share the same shape: a limit or a stale value fails quietly instead of loudly.

Issue #45 found that CACHE_DIR was computed from process.cwd() at module load time, so running infrawise analyze from one directory and infrawise dev from another meant the second command silently read a cache built for a different invocation path — no mismatch warning, just answers that looked current and weren’t. Issue #38 found that --no-cache was accepted by the CLI parser but never actually read by runAnalyze, so a developer explicitly asking for a fresh scan got a cached one anyway, with no indication the flag had been ignored. And issue #39 found that LambdaMissingTriggerDLQAnalyzer was wired into the one-time infrawise analyze path but missing from runCodeRefresh, the path the file watcher calls on every save — so DLQ findings that showed up on the first run quietly vanished after the first edit, with the developer none the wiser.

Different subsystems, same failure mode: nothing crashed, nothing logged, the tool just answered with less than it should have and gave no sign of it. For a tool that stakes its value on being more trustworthy than an LLM’s guess, “wrong but confident” is the one failure mode it can’t afford — and it’s the one that shipped three separate times before anyone caught it.

The fix

The fix for #40 was a one-line diff:

- } while (marker && functions.length < 200);
+ } while (marker);

Enter fullscreen mode Exit fullscreen mode

Pagination now runs until AWS says there’s nothing left, full stop. The fix direction noted in the issue also called for a warning log if pagination ever gets cut short for another reason — worth keeping in mind if you’re building a similar extraction loop: an arbitrary safety cap on a paginated API call is rarely wrong to have, but silence when it triggers always is. A logger.warn costs one line and turns a silent data gap into a debuggable one.

If you’re pointing an AI assistant at your own AWS account and it has more than 200 Lambda functions, this fix landed in the same release cycle as the other three — worth confirming you’re on a current version.

GitHub · npm

Key Takeaways

  • A pagination cap with no warning is a silent data-loss bug waiting for an account large enough to trigger it — 200 felt generous until “larger orgs” turned out to be the target audience.
  • Distinguish “checked and found nothing” from “never checked” in any analyzer or query result — collapsing them into the same empty response is the failure mode that erodes trust fastest.
  • Audit every loop bounded by both a natural termination condition (a pagination marker) and an arbitrary one (a hardcoded count) — the arbitrary one is usually the one that fails silently.
  • Cache keys derived from process.cwd() or other invocation-time state can go stale in ways a static cache TTL never catches — tie cache identity to something stable, not to where the process happened to start.
  • If a CLI flag exists, verify the code path actually reads it. --no-cache sitting in the parser but unused is exactly the kind of gap that only turns up when someone reads the issue tracker, not the tests.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다