Files
jakevin 6557622156 fix(adapters): surface empty results as EmptyResultError, not sentinel rows (#1981)
* fix(adapters): surface empty results as EmptyResultError, not sentinel rows

Four adapters returned a fabricated row (exit 0) on the not-found/empty
path instead of throwing a typed error, so an agent reading the exit code
or rows could not tell "no results" from success — the framework assigns
EMPTY_RESULT its own exit code precisely so this is detectable:

- maimai/search-talents: returned [{error, query}] on zero candidates.
  Worse, `error`/`query` are not in `columns`, so the message was dropped
  by column projection — the user saw an empty/garbage row, never the
  reason. Now throws EmptyResultError (fixes the silent-column-drop too).
- discord-app/search: returned a synthetic "System" row on no matches.
- pixiv/download: returned a failed sentinel when an illust had 0 pages
  (the file already throws typed errors elsewhere). Test updated to
  assert the throw.
- xiaohongshu/download: returned a failed sentinel when a note had no
  media (the file already throws CliError for the security-block branch).

Per-image partial-failure status rows in the download loops are left
as-is (legitimate batch reporting). Auth-path conversions
(tiktok/facebook string-prefix + maimai in-page throw) are a separate
follow-up since they involve in-page-throw handling.

Adapter suites green; typed-error-lint and silent-column-drop audits
report no new violations.

* fix(adapters): fail closed on malformed empty payloads

* fix(audit): bump undici in lockfile

* fix(pixiv): fail closed on missing pages payload

---------

Co-authored-by: codex-mini0 <codex-mini0@slock.local>
2026-06-21 15:44:19 +08:00
..