sfge: path evaluation never converges on a ~40-field DTO mapper, silently abandoning every entry point that reaches it
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- java, typescript
Hướng nghiên cứu
Tái hiện quá trình quét ApexFlsViolation với đường dẫn điểm vào → phương thức đọc → DTO mapper và vòng lặp ~40 trường được mô tả trong issue. Bắt đầu bằng cách lần theo timeout của Graph Engine và việc xử lý các entry bị bỏ dở xung quanh PathScopeVisitor cùng các stack frame SyntheticTypedVertex/ApexMapValue được liệt kê. Phần hoàn tất phải bao gồm bản tóm tắt rõ ràng hoặc việc thoát với mã khác 0 đối với các điểm vào bị bỏ dở, cùng với chẩn đoán hoặc bản sửa lỗi hội tụ cho đường dẫn mapper.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
Graph Engine path evaluation never completes for a method shaped like an ordinary DTO mapper — a for loop that assigns ~40 fields from an SObject onto a new inner-class instance. Every @AuraEnabled entry point whose call graph reaches that method is abandoned with Path evaluation timed out after N ms, at any timeout value we tried.
The mapper is the main view builder for a customer community portal, so this is not an unusual corner of the codebase — it is on the hot path of most entry points.
Versions
@salesforce/[email protected][email protected]- Rule:
ApexFlsViolation(sfge, DevPreview) - Linux: GitHub-hosted
ubuntu-latest, and reproduced innode:22-bookwormwith OpenJDK 17 - Observed 2026-08-20
The most important part: it fails silently
When path evaluation times out, the entry point is abandoned and no findings are reported for it. The scan then prints:
Found 0 violations.
and exits 0.
Found 0 violations is indistinguishable from "0 violations in the parts that finished". We only discovered that ~5% of our entry points were never analysed because we had added a step that greps the run's own log for Internal execution error. Anyone gating CI on this rule without that grep is gating on an unknown subset of their code and has no way to know.
This is the part we would most like fixed, independently of the convergence bug. An abandoned entry point should be visible in the exit code or in a summary, not only in a log line.
Isolation
We bisected by modifying a copy of the tree and re-running the identical command. Baseline is unmodified.
| # | Change under test | Elapsed | Timeout? |
|---|---|---|---|
| — | baseline | 344s | yes |
| A | deleted 2 classes downstream of the entry point | 341s | yes |
| B | replaced a per-character if/else chain with a Map lookup |
352s | yes |
| C | deleted all 12 classes in the downstream call tree | 360s | yes |
| D | baseline ×2 (determinism check) | 342s / 348s | yes |
| E | sfge-disable-stack on the entry points |
350s | yes |
| F | stubbed the body of the read method the entry point calls | 63s | no |
| G | removed only the call to that read method | 258s | no |
| H | stubbed the DTO mapper that read method calls | 165s | no |
| I | stubbed a sibling call | 347s | yes |
| J | stubbed another sibling call | 345s | yes |
| K | stubbed four more sibling calls | 340s | yes |
H is the finding. The offending method is reached as: entry point → read method → DTO mapper. Stubbing the mapper drops the run below the timeout so it cannot fire.
We then bisected inside the mapper. None of these had any effect (~340s each, i.e. the timeout still fired):
- the one reflective read,
(Id) record.getPopulatedFieldsAsMap().get('SomeField__c') - a call into another class returning a
Boolean - two short-circuit
&&chains
So it does not appear to be any individual construct. What remains is the shape: a loop assigning ~40 fields onto a newly constructed object.
We attempted to test whether time scales with field count, but our patch produced invalid Apex for two of the three variants (the analyser ran fast and reported no errors, which we read as the class failing to parse rather than as a result). We are not claiming the field count is the cause — only that no single line in the method is, and that this is where it would be worth your engineers looking.
sfge-disable-stack does not help
Documented here for others: putting /* sfge-disable-stack ApexFlsViolation */ on the affected entry points changed nothing (E, 350s). The directive suppresses rule evaluation; the timeout happens earlier, during path expansion.
Raising the timeout does not help either
java_thread_timeout was already raised from the 30s default to 300s for an unrelated entry point. The method above does not converge at 300s and, from the shape of it, would not converge at any practical value — so the timeout is spent in full and then the entry point is dropped regardless. Lowering it trades coverage for speed; raising it trades speed for nothing.
Possibly related, same run
A different entry point in the same codebase throws, rather than timing out. It passes a Map<String, Object> into a service method:
Internal execution error while scanning entry point: <redacted>.cls:739:
Graph Engine identified your source and sink, but you must manually verify
that you have a sanitizer in this path. [...]
Error and stacktrace: NullPointerException: null:
java.base/java.util.concurrent.ConcurrentSkipListMap.computeIfAbsent(ConcurrentSkipListMap.java:1459)
com.salesforce.graph.vertex.SyntheticTypedVertex.get(SyntheticTypedVertex.java:41)
com.salesforce.graph.symbols.apex.ApexMapValue.apply(ApexMapValue.java:188)
com.salesforce.graph.symbols.PathScopeVisitor.handleApexValueMethod(PathScopeVisitor.java:1487)
com.salesforce.graph.symbols.PathScopeVisitor.afterVisit(PathScopeVisitor.java:1242)
com.salesforce.graph.symbols.DefaultSymbolProviderVertexVisitor.afterVisit(DefaultSymbolProviderVertexVisitor.java:800)
We have also previously seen the engine throw on Map<Integer, Integer> and on Decimal.setScale, and reshaped code to avoid both.
What would help, in priority order
- A non-zero exit, or an explicit summary line, when entry points are abandoned. Silent under-analysis is worse than a slow scan.
- A diagnostic for why expansion does not converge — a path or branch count, or a verbose mode naming the expansion site. The only signal today is "it timed out", which is what forced the twelve-run bisection above.
- The convergence fix itself.
Outcome for us
We have removed ApexFlsViolation from our blocking gate and moved it to a nightly advisory report. The gate went from 344s to 13s. We would rather have the rule back on the gate, and will re-arm it if this is fixed.
Happy to run further bisections against a diagnostic build, or to share the method under NDA.
- Ngôn ngữ chính
- TypeScript
- Star
- 241
- Fork
- 52
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của forcedotcom/code-analyzer
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
forcedotcom/code-analyzer#2106 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
forcedotcom/code-analyzer#2094 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
forcedotcom/code-analyzer#2093 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
forcedotcom/code-analyzer#2091 ·
-
[BUG][code-analyzer] sfge: calling toString() on an enum aborts the entry point (UnimplementedMethodException)Có thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
forcedotcom/code-analyzer#2090 ·
Tất cả issue của forcedotcom/code-analyzer
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
scaleway/ultraviolet#7089 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
tencent-connect/dsh-qqbot#81 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug]: Pen taps on sidebar rows start a drag and lose their clickCó thể đã có người làm @makhnatkin đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
clangd/vscode-clangd#1009 ·