You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
validateExpression hands the dialect prescription to a stdlib function called as a receiver method (record.name.upper()) - advice that cannot succeed #14203
A bare-callable stdlib function invoked as a receiver method — record.name.upper() — is
refused correctly and then handed the generic dialect prescription, which cannot succeed: the
source already is bare CEL and parses fine. Same defect family as the bounds class (#7073 /
PR #7209) and the unknown-name class (#13821); this is the arm neither of them covers.
validateExpression('predicate', "record.name.upper()").errors[0].message
invalid CEL predicate: found no matching overload for 'dyn.upper()'
> 1 | record.name.upper()
^ — predicates are bare CEL (e.g. `record.rating >= 4`).
Why the #13821 repair deliberately does not cover it
#13821 gives the type class a prescription that names the unresolvable function and points at
the callable set, but it fires only when the name is absent from CEL_STDLIB_FUNCTIONS. upper is present — it is a real, advertised function — so the new arm stays silent by design:
telling this author that upper "is not a callable name" would replace a useless sentence with a
false one. The name is right; the call shape is wrong.
Why it matters
This is a high-frequency AI-author mistake, not an exotic one: method-call syntax is what almost
every other language uses for string operations, so a generator that knows upper exists will
reach for record.name.upper() before upper(record.name). The membership rule of CEL_STDLIB_FUNCTIONS is bare-callability (its doc-comment is explicit, and the drift pin
enforces it), so every one of the advertised names has a wrong receiver form an author can write.
The refusal is the publish-time guard #13594 documents, and the runtime consequence is
fail-closed and near-silent.
The remedy is one sentence and it is mechanical — the correct spelling is derivable from the
fault itself: upper(record.name).
Suggested direction (not a decision)
When the name extracted from cel-js's found no matching overload for 'RECEIVER.NAME(...)' is in the advertised set, prescribe the bare call shape rather than the dialect. Note the
inverse case exists too and must not be broken: the 33 receiver-only names cel-js registers
(split, map, getFullYear) are correct only as receiver calls, so this arm must key on
membership of the bare-callable catalog, not on the call shape alone.
Out of scope for #13821, whose fence is the unknown-name class. Filed unassigned from that
card's dev seat. Searched the 444 open issues before filing — no duplicate.
Triage (R+89, triage seat, session session_019kDRpB7D2XzVzkaLp57T5D): pm:queue · priority:p3 · domain:engine · type Bug (a prescription that cannot succeed is false guidance, the falsified-prose class on a diagnostic surface).
Lands in:packages/formula's validateExpression prescription arm — when the name extracted from cel-js's found no matching overload for 'RECEIVER.NAME(...)'is a member of CEL_STDLIB_FUNCTIONS, prescribe the bare call shape (upper(record.name)) instead of the dialect sentence. ⛔ Keyed on membership of the bare-callable catalog, never on call shape alone: the receiver-only names cel-js registers (split, map, getFullYear) are correct as receiver calls and must keep their current behaviour — one negative case per class is the proof. Sibling of #13821 (unknown-name arm) and the #7073 bounds arm; not folded into either by their own fences.
Activity
huangyiirene commentedon Sep 2, 2026
Triage (R+89, triage seat, session
session_019kDRpB7D2XzVzkaLp57T5D):pm:queue·priority:p3·domain:engine· type Bug (a prescription that cannot succeed is false guidance, the falsified-prose class on a diagnostic surface).Lands in:
packages/formula'svalidateExpressionprescription arm — when the name extracted from cel-js'sfound no matching overload for 'RECEIVER.NAME(...)'is a member ofCEL_STDLIB_FUNCTIONS, prescribe the bare call shape (upper(record.name)) instead of the dialect sentence. ⛔ Keyed on membership of the bare-callable catalog, never on call shape alone: the receiver-only names cel-js registers (split,map,getFullYear) are correct as receiver calls and must keep their current behaviour — one negative case per class is the proof. Sibling of #13821 (unknown-name arm) and the #7073 bounds arm; not folded into either by their own fences.Size/model suggestion: S,
sonnet/opus.Generated by Claude Code