跳到正文
DEV Community· Jeff·· 2 小時前AI 評分56

AI 智能體加入「安全」後備處理,悄悄回傳空資料

The Agent Added a 'Safe' Fallback That Quietly Returned Empty Data

AI 導讀

文章指出,AI 智能體生成程式碼時若把請求故障也處理成空資料,介面便會顯示空清單,錯誤亦可能在正式環境中被掩蓋。`?? []` 適用於合約明確允許缺值的欄位;HTTP 請求失敗通常會拋出例外,真正掩蓋問題的往往是捕捉例外後回傳空陣列。文章建議分開處理可選欄位與請求錯誤,並分別測試空結果及網絡錯誤時的介面狀態和重試處理。

正文

Quick answer: A nullish fallback like data ?? [] is a legitimate way to handle a value that is genuinely optional, but an AI agent often reaches for it to silence a type error or an "cannot read property of undefined" crash. The result is a silent failure: when the upstream call actually breaks, the UI renders an empty list instead of surfacing the error, and the bug hides in production. Treat the fallback as a decision about what the failure mode should be, not as a syntax fix.

How the empty fallback gets introduced

Here is the typical chain. The agent is wiring a profile page to a service that returns a list of projects. The OpenAPI contract marks the field as present, but the generated type says it can be undefined because the response uses an optional wrapper. The agent sees a type error on projects.map, and the fastest way to make the checker green is to default it.

On the surface this is reasonable. The problem is that ?? [] collapses two very different situations into one branch. A field that is legitimately absent and a network call that threw and returned nothing now look identical. In most generated clients, a failed HTTP request does not return undefined at all; it throws, and a separate catch that returns an empty array is usually where the real masking happens.

Why an empty screen is worse than a loud error

An error that throws is cheap to diagnose. You get a stack, a status code, and a failed request in the network panel. An empty list gives you none of those. The user sees "no projects yet," assumes they simply have not created any, and never reports it. The team's error tracker stays quiet because nothing was thrown. This is the precise failure mode that makes agent-written code feel trustworthy in a demo and unreliable months later.

Behavior Loud failure Empty fallback
What the user sees An error state or retry prompt A blank section that looks intentional
Error tracker Receives the exception Nothing is reported
Time to detect Immediate Weeks, often via a support ticket
Recovery User can retry User must refresh and hope

Where the fallback is actually correct

Do not read this as a ban on ?? []. The operator is correct when the empty value is an expected, documented state. A search endpoint that returns an empty array for zero matches is a real answer, not a failure. A feature flag payload that omits a new field for older clients is also a legitimate optional value. The distinction is whether the empty branch represents a valid domain state or a swallowed infrastructure error.

A safer pattern that keeps both cases honest

Separate the optional-field handling from the error handling. Let the request throw on transport and status failures, and only default the specific field that the contract says can be absent.

If the upstream genuinely returns null to mean "not found" rather than an error, encode that explicitly with a named branch so a reviewer can see the intent. A comment and a named constant beat an operator that disappears into a long expression.

const NOT_FOUND = null; const projects = response === NOT_FOUND ? [] : response.projects;

How to catch it in review

When you review an agent-generated diff, search for the spots where a fallback was added in the same commit as the code that consumes the value. Ask one question: is this an optional domain field, or is the agent papering over a call that can fail? If the diff includes a catch that returns [], {}, or an empty string, that is the highest-risk line in the change, because it converts every exception into a successful-looking response. Require the agent to add a test for the failure branch, not just the empty-list branch.

Frequently asked questions

Is ?? [] always a bug when an AI adds it?

No. It is correct for values the contract declares optional and for endpoints where an empty result is a meaningful answer. It is a bug when it is used to make a failing request look successful or to silence a type error without checking why the value can be undefined.

What about the optional chaining I added to avoid a crash?

Optional chaining and nullish defaults are useful for defensive rendering, but they should sit at the boundary of a well-defined optional value. If you find yourself chaining them several levels deep to navigate a response the API promised would be shaped differently, that is a sign the type or the request is wrong, not a reason to keep adding operators.

Should the agent ever catch and return an empty array?

Only as a deliberate, documented product decision, and usually not. A catch block that returns empty data hides the error from both the user and monitoring. Prefer rethrowing, reporting to your error tracker, and rendering an explicit retry state.

How do I test the difference between empty and broken?

Write two cases. Mock the client to resolve with an empty array and assert the empty state renders, then mock it to reject with a network error and assert the error state and retry handler appear. A test suite that only covers the empty branch is exactly how this defect survives.

This is part of the The AI Coding Agent Guide — start there for the full picture of how agent-written code fails in practice and how to review it.

來源:DEV Community · dev.to