Bug: eventFilterMatches returns false for nested $exists: false when the parent key is missing or null

オープン 初心者向け
#5,017 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

  • #5023 @GauravPatil2515 による — マージされずにクローズ
  • #5099 @cocvn157 による — マージされずにクローズ

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
78/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
node.js, typescript
領域
backend, testing

調査の方向性

まず packages/core/src/eventFilterMatches.ts と packages/core/test/eventFilterMatches.test.ts の既存ケースを確認します。issue にあるネストされた $exists: false のケースを、親キーが存在しない場合と null の場合も含めて再現し、その後、トップレベルのケースが引き続き通ることを確認します。報告された4つの結果がすべて true を返し、既存のテストが通れば完了です。

索引モデルが issue の本文から書いたものです。

説明

Summary

eventFilterMatches returns false for a nested $exists: false filter when the parent key is missing or null in the payload. The function returns false for any non-empty filter as soon as it meets an undefined/null payload, before it evaluates $exists. This is user-facing through retry.fetch's bodyFilter, which calls eventFilterMatches on the response body.

Reproduction

  1. Setup: packages/core on main.
  2. Command: npx tsx repro.ts from packages/core with:
import { eventFilterMatches } from "./src/eventFilterMatches.js";
const f = { user: { email: [{ $exists: false }] } };
console.log(eventFilterMatches({}, f));             // false
console.log(eventFilterMatches({ user: null }, f)); // false
console.log(eventFilterMatches({ user: {} }, f));   // true
console.log(eventFilterMatches({}, { email: [{ $exists: false }] })); // true
  1. Trigger: a nested filter whose leaf is $exists: false, used with a payload where an ancestor key is absent or null.

Actual behavior

{} {"user":{"email":[{"$exists":false}]}} => false
{"user":null} {"user":{"email":[{"$exists":false}]}} => false
{"user":{}} {"user":{"email":[{"$exists":false}]}} => true
{} {"email":[{"$exists":false}]} => true

Expected behavior

All four should return true. If user is missing, then user.email doesn't exist either, which is exactly what $exists: false asserts. Top-level $exists: false already behaves that way (case 4, and the existing test "should return true when payload does NOT have a key that $exists = false"). Nesting the same condition one level deeper shouldn't flip the result.

Environment

  • Version/commit: main @ 93465d8549a735074d1ce7696bae3faebe577e8d
  • OS: Ubuntu (Linux), Node v24.21.0
  • Relevant configuration: none; pure function. Reachable from retry.fetch(url, { retry: { byStatus: { "...": { strategy: "backoff", bodyFilter } } } })

Evidence

Additional context

Confirmed: the four results above, from running the source on main.

Inference: for retry.fetch, a bodyFilter such as { error: { retryAfter: [{ $exists: false }] } } won't match a body that has no error object at all. That strategy is then skipped. I haven't exercised this through retry.fetch end to end.

Possible fix: when the payload is undefined/null, evaluate the filter against an empty object (or recurse with {}) instead of returning false, so that $exists: false and $isNull-style leaves still get evaluated.

Found with an anti-slop oxlint scan (no-runtime-typeof), then checked by hand.

主要言語
TypeScript
スター
16.5k
フォーク
1.5k
平均マージ
1日 15時間
マージ済み PR(30日)
17

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

triggerdotdev/trigger.dev のほかの issue

triggerdotdev/trigger.dev の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。