Summary
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.
Measured
packages/formula @ 4d672c4f, @marcbachmann/cel-js@8.0.0:
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.
Generated by Claude Code
Summary
A bare-callable stdlib function invoked as a receiver method —
record.name.upper()— isrefused 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
boundsclass (#7073 /PR #7209) and the unknown-name class (#13821); this is the arm neither of them covers.
Measured
packages/formula@4d672c4f,@marcbachmann/cel-js@8.0.0:Why the #13821 repair deliberately does not cover it
#13821 gives the
typeclass a prescription that names the unresolvable function and points atthe callable set, but it fires only when the name is absent from
CEL_STDLIB_FUNCTIONS.upperis 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 afalse 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
upperexists willreach for
record.name.upper()beforeupper(record.name). The membership rule ofCEL_STDLIB_FUNCTIONSis bare-callability (its doc-comment is explicit, and the drift pinenforces 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 onmembership 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.
Generated by Claude Code