You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by "vamsizzz (via GitHub)" <gi...@apache.org> on 2026/09/22 01:44:25 UTC
[I] Drools PhreakFromNode NPE [incubator-kie]
vamsizzz opened a new issue, #7125:
URL: https://github.com/apache/incubator-kie/issues/7125
---
## 1. Symptom (production)
```
java.lang.NullPointerException: Cannot invoke "java.util.Map.remove(Object)" because "<local18>" is null
at org.drools.core.phreak.PhreakFromNode.doLeftUpdates(PhreakFromNode.java:141)
at org.drools.core.phreak.PhreakFromNode.doNode(PhreakFromNode.java:97)
at org.drools.core.phreak.RuleNetworkEvaluator.evalNode(RuleNetworkEvaluator.java:403)
at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:349)
at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:185)
at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:143)
at org.drools.core.phreak.RuleExecutor.evaluateNetwork(RuleExecutor.java:221)
at org.drools.core.phreak.RuleExecutor.evaluateNetworkIfDirty(RuleExecutor.java:231)
at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:76)
at org.drools.kiesession.agenda.DefaultAgenda.fireLoop(DefaultAgenda.java:624)
...
at org.drools.kiesession.session.StatelessKnowledgeSessionImpl.execute(StatelessKnowledgeSessionImpl.java:271)
```
It does **not** reproduce when replaying the same request directly against a freshly-cold-loaded KJAR. It **only** reproduces when the running `KieContainer` reaches that KJAR version via a chain of `KieContainer.updateToVersion()` hot-reloads (e.g. v8 → v14 → v16 → v17), and it reproduces **100% of the time** once that history exists.
---
## 2. The immediate defect: missing null-guard
`org.drools.core.phreak.PhreakFromNode.java` (stock 8.44.0.Final), method `doLeftUpdates`, line 141:
```java
public void doLeftUpdates(FromNode fromNode,
FromMemory fm,
LeftTupleSink sink,
ReteEvaluator reteEvaluator,
TupleSets<LeftTuple> srcLeftTuples,
TupleSets<LeftTuple> trgLeftTuples,
TupleSets<LeftTuple> stagedLeftTuples) {
...
for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple != null; ) {
LeftTuple next = leftTuple.getStagedNext();
PropagationContext propagationContext = leftTuple.getPropagationContext();
final Map<Object, RightTuple> previousMatches = (Map<Object, RightTuple>) leftTuple.getContextObject(); // <-- can be null
final Map<Object, RightTuple> newMatches = new HashMap<>();
leftTuple.setContextObject( newMatches );
...
for (... it.hasNext(); ) {
...
RightTuple rightTuple = previousMatches.remove(object); // <-- NPE here
...
}
for (RightTuple rightTuple : previousMatches.values()) { ... } // <-- would also NPE
...
}
}
```
There is **zero defensive check** on `previousMatches`. The method assumes unconditionally that whatever inserted this `LeftTuple` also called `leftTuple.setContextObject(matches)`. That assumption is false whenever the node was built with left-tuple memory disabled — see below.
Compare with `doLeftInserts` in the same file, which explicitly branches on whether memory is enabled:
```java
public void doLeftInserts(FromNode fromNode, FromMemory fm, LeftTupleSink sink,
ReteEvaluator reteEvaluator,
TupleSets<LeftTuple> srcLeftTuples, TupleSets<LeftTuple> trgLeftTuples) {
...
for (LeftTuple leftTuple = srcLeftTuples.getInsertFirst(); leftTuple != null; ) {
...
Map<Object, RightTuple> matches = null;
boolean useLeftMemory = RuleNetworkEvaluator.useLeftMemory(fromNode, leftTuple);
if (useLeftMemory) {
fm.getBetaMemory().getLeftTupleMemory().add(leftTuple);
matches = new LinkedHashMap<>();
leftTuple.setContextObject( matches ); // <-- only set when useLeftMemory == true
}
...
}
}
```
So `doLeftInserts` correctly *skips* populating the context map when `useLeftMemory == false`. `doLeftUpdates` never checks for that case at all.
---
## 3. Why `useLeftMemory` is false: `sequential="true"` bakes it in at compile time
`RuleNetworkEvaluator.useLeftMemory()`:
```java
public static boolean useLeftMemory(LeftTupleSource tupleSource, Tuple tuple) {
boolean useLeftMemory = true;
if (!tupleSource.isLeftTupleMemoryEnabled()) {
Object object = tuple.getRootTuple().getFactHandle().getObject();
if (!(object instanceof DroolsQueryImpl) || !((DroolsQueryImpl) object).isOpen()) {
useLeftMemory = false;
}
}
return useLeftMemory;
}
```
`isLeftTupleMemoryEnabled()` on a `FromNode` traces back to a plain field baked in once, at node-construction time, by `FromBuilder`:
```java
// org.drools.core.reteoo.builder.FromBuilder#build
FromNode fromNode = from.isReactive()
? nodeFactory.buildReactiveFromNode(context.getNextNodeId(), from.getDataProvider(),
context.getTupleSource(), alphaNodeFieldConstraints, betaConstraints,
context.isTupleMemoryEnabled(), // <-- baked in permanently here
context, from)
: nodeFactory.buildFromNode(context.getNextNodeId(), from.getDataProvider(),
context.getTupleSource(), alphaNodeFieldConstraints, betaConstraints,
context.isTupleMemoryEnabled(), // <-- and here
context, from);
```
And `context.isTupleMemoryEnabled()` is decided **once per rule compile, purely from the KieBase's `sequential` flag** — nothing to do with whether that specific pattern needs memory for joins:
```java
// org.drools.core.reteoo.builder.ReteooRuleBuilder#addRule, line ~130
if (kBase.getRuleBaseConfiguration().isSequential()) {
context.setTupleMemoryEnabled( false );
} else {
context.setTupleMemoryEnabled( true );
}
```
Confirmed against the actual production KJAR (`uswm-v17.kjar`, extracted `kmodule.xml`):
```xml
<kbase name="Substantiation.Direct Spend or Exclusion list only"
packages="rules.substantiation.direct_spend" sequential="true">
<ksession name="Substantiation.Direct Spend or Exclusion list only" type="stateless"/>
</kbase>
<!-- every other kbase in the module is also sequential="true" -->
```
**Sequential mode's entire premise is "insert once, fire in salience order, never re-evaluate."** Left-tuple memory (the map that tracks "what matched last time so I can diff on the next update") is a bookkeeping cost Drools deliberately skips in that mode, because sequential mode's contract says nothing should ever need to be revisited. `update()`/`modify()` calls violate that contract for a `from`-bound fact — and Drools does not validate or reject the combination anywhere at compile time or session time. It just leaves a landmine.
---
## 4. Instrumented, reproducible proof (not inference)
We patched `PhreakFromNode.java` with diagnostic logging (see full patch below), rebuilt a patched `drools-core-8.44.0.Final.jar`, put it first on the classpath ahead of the real one, and replayed the known-poisoned hot-reload chain `v8 → v14 → v16 → v17` against the exact production request that fails.
### Patch used for instrumentation
```java
public class PhreakFromNode {
private static final boolean DIAG =
Boolean.parseBoolean(System.getProperty("phreak.fromnode.diag", "true"));
private static void diag(String fmt, Object... args) {
if (DIAG) System.out.println("[PHREAK-FROMNODE-DIAG] " + String.format(fmt, args));
}
// ... doLeftInserts(): log node identity + useLeftMemory decision on every insert
diag("INSERT node=%s tuple=%s useLeftMemory=%s existingContextObject=%s",
nodeId(fromNode), tupleId(leftTuple), useLeftMemory,
leftTuple.getContextObject() == null ? "null" : leftTuple.getContextObject().getClass().getSimpleName());
// ... doLeftUpdates(): log + dump full diagnostic BEFORE the original NPE fires
Object rawContextObject = leftTuple.getContextObject();
if (rawContextObject == null) {
// dumps node id, tuple, rule, dataProvider, resultClass, reteEvaluator identity
// then falls through to the *original* unmodified cast+dereference so the
// stack trace / behavior is unchanged for apples-to-apples comparison with prod
}
final Map<Object, RightTuple> previousMatches = (Map<Object, RightTuple>) rawContextObject;
```
### Result
| KJAR version | Executions on shared `FromNode` (JVM identity `FromNode@1234d9f6`, node id `17236`) | Inserts | Updates | Result |
|---|---|---|---|---|
| v8 (cold load) | 200 | 200 | **0** | OK — never touches update path |
| v14 (`updateToVersion`) | 200 | 200 | **0** | OK |
| v16 (`updateToVersion`) | 200 | 200 | **0** | OK |
| v17 (`updateToVersion`) | 100 | 100 | **100** | **100/100 NPE** |
Every single insert across all four versions logs:
```
[PHREAK-FROMNODE-DIAG] INSERT node=FromNode@1234d9f6 id=17236 tuple=JoinNodeLeftTuple@... useLeftMemory=false existingContextObject=null
[PHREAK-FROMNODE-DIAG] INSERT node=FromNode@1234d9f6 id=17236 tuple=JoinNodeLeftTuple@... -> contextObject NOT SET (useLeftMemory=false); leftTuple.contextObject stays null
```
The very first `UPDATE` this node has ever seen across the whole run happens immediately after the `updateToVersion()` jump to v17, and crashes on the first try:
```
UPDATE -> com.walmart.tender:tender-rules-kjar:1.0.17-USWM
results=[]
[PHREAK-FROMNODE-DIAG] UPDATE node=FromNode@1234d9f6 id=17236 tuple=JoinNodeLeftTuple@1d0d4478 rawContextObject=NULL (class=n/a) ...
[PHREAK-FROMNODE-DIAG] *** previousMatches IS NULL - about to NPE ***
node=FromNode@1234d9f6 id=17236
tuple=JoinNodeLeftTuple@1d0d4478
leftTuple.toString=[fact 0:1:774893764:774893764:4:DEFAULT:NON_TRAIT:...RuleContext{programApplied=true, decisionGroup='', hasRequest=true, hasResponse=true}]
fromNode.getDataProvider=org.drools.mvel.dataproviders.MVELDataProvider@3b453e37
fromNode.getResultClass=class ...ApplyOffersRequest
reteEvaluator=KieSession[403]
FAILED com.walmart.tender:tender-rules-kjar:1.0.17-USWM#1: java.lang.NullPointerException: Cannot invoke "java.util.Map.remove(Object)" because "<local18>" is null
```
**Key finding:** `useLeftMemory=false` is present on *every single insert in every version*, including v8/v14/v16 which never crash. The crash isn't caused by the flag suddenly flipping — it's caused by v17's newly patched-in rule content being the first version whose consequence chain actually calls `update()` in a way that routes back through this exact, already-memory-disabled, **shared** `FromNode` object. A from-scratch cold compile of v17 alone does not reproduce it for the same request — only the incremental `updateToVersion()` history does. That strongly suggests Drools' incremental node-sharing/reuse logic during hot-reload wires new rule consequences to pre-existing shared nodes differently (and more dangerously) than a batch/from-scratch compile does, on top of the pre-existing sequential-mode landmine.
### Node-sharing path checked (for completeness)
`org.drools.core.reteoo.builder.BuildUtils#attachNode` is where Drools decides whether to reuse an existing compatible node or build a new one:
```java
} else if ( isSharingEnabledForNode(context, candidate) ) {
if ( (context.getTupleSource() != null) && NodeTypeEnums.isLeftTupleSink(candidate) ) {
node = context.getTupleSource().getSinkPropagator().getMatchingNode(candidate);
}
...
}
if ( node != null && !areNodesCompatibleForSharing(context, node) ) {
node = null;
}
```
Because `tupleMemoryEnabled` is a **KieBase-wide** setting (driven purely by `sequential`), every `FromNode` built anywhere in this kbase — whether during a fresh compile or an incremental patch — computes the same `false` value. So `areNodesCompatibleForSharing` never sees a mismatch to reject; sharing a memory-disabled node across rule versions is "correct" by Drools' own compatibility check, it's just that the underlying premise (no rule will ever call `update()` through it) turns out to be false once v17 adds a consequence that does.
---
## 5. Suggested fix (for the upstream ticket)
Two independent, complementary fixes:
1. **Defensive null-check in `PhreakFromNode.doLeftUpdates()`** — if `previousMatches` is null (i.e., this node was built without left-tuple memory), either:
- treat it as an empty map (degrade gracefully — matches sequential-mode's "don't bother" intent), or
- throw a clear, actionable exception (`IllegalStateException: update()/modify() is not supported for 'from' bindings in a sequential-mode KieBase — node <id>, rule <rule>`) instead of a bare NPE.
2. **Compile-time or build-time validation** that rejects (or at least warns on) `update()`/`modify()` calls whose propagation reaches a `from` node in a `sequential="true"` kbase, so this is caught during `kieBuilder.buildAll()` instead of at runtime under specific hot-reload histories.
---
## 6. Public-safe minimal repro (use this when filing the GitHub issue — do not paste our internal package names)
```java
// kmodule.xml
// <kbase name="repro" sequential="true"><ksession name="repro" type="stateless"/></kbase>
// Repro.drl
rule "insert-holder"
when
$ctx : Holder()
$x : String() from $ctx.items // from-binding on a mutable field
then
// no-op
end
rule "mutate-and-update"
salience 100
when
$ctx : Holder(applied == false)
then
$ctx.setApplied(true);
update($ctx); // <-- triggers doLeftUpdates() on the shared FromNode above
end
```
```java
StatelessKieSession session = container.newStatelessKieSession("repro");
session.execute(new Holder());
// NPE: java.lang.NullPointerException at org.drools.core.phreak.PhreakFromNode.doLeftUpdates
```
Note in the ticket that in our real-world case the crash was only observed after several `KieContainer.updateToVersion()` hot-reloads of a growing ruleset — a from-scratch compile of the final ruleset alone did not reproduce it, which may point to a secondary defect in incremental node-sharing during `updateToVersion()`.
---
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "yesamer (via GitHub)" <gi...@apache.org>.
yesamer commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-5790359837
@vamsizzz
Thiis issue
```
NPE: DoubleLinkedEntry.getPrevious() is null
at org.drools.core.util.LinkedList.remove(LinkedList.java:178)
at org.drools.core.util.index.TupleList.remove(TupleList.java:51)
at org.drools.core.phreak.PhreakFromNode.doLeftDeletes(PhreakFromNode.java:207)
```
should be already resolved, we already provided a patch for that. It will be available in the next release.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "vamsizzz (via GitHub)" <gi...@apache.org>.
vamsizzz commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-5798990655
> [@vamsizzz](https://github.com/vamsizzz)
>
> Thiis issue
>
> ```
> NPE: DoubleLinkedEntry.getPrevious() is null
> at org.drools.core.util.LinkedList.remove(LinkedList.java:178)
> at org.drools.core.util.index.TupleList.remove(TupleList.java:51)
> at org.drools.core.phreak.PhreakFromNode.doLeftDeletes(PhreakFromNode.java:207)
> ```
>
> should be already resolved, we already provided a patch for that. It will be available in the next release.
Thanks a ton!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "yesamer (via GitHub)" <gi...@apache.org>.
yesamer commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-6191260950
@Rikkola @tkobayas ^^
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "tkobayas (via GitHub)" <gi...@apache.org>.
tkobayas closed issue #7125: Drools PhreakFromNode NPE 8.44.0.Final
URL: https://github.com/apache/incubator-kie/issues/7125
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "yesamer (via GitHub)" <gi...@apache.org>.
yesamer commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-5772694007
Hi @vamsizzz, thank you for reporting.
In general I would suggest you to use a newer Apache KIE version, 8.44 is very old and no longer supported. Can you please doublecheck if the same reproduces with latest 10.2 versioN?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "mvanhorn (via GitHub)" <gi...@apache.org>.
mvanhorn commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-6191232396
The from update path loads the previous-match map from the left tuple context and uses it immediately. Sequential mode builds that from node with tuple memory disabled, so the insert path never stores the map and the update path dereferences null.
The from update path now throws IllegalStateException when that map is missing, stating that update or modify through a from binding is unsupported while sequential mode has disabled tuple memory.
https://github.com/apache/incubator-kie/pull/7192
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "yesamer (via GitHub)" <gi...@apache.org>.
yesamer commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-6453805514
@tkobayas Can we close this? I see the linked PR was merged.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "vamsizzz (via GitHub)" <gi...@apache.org>.
vamsizzz commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-5788669328
> Hi [@vamsizzz](https://github.com/vamsizzz), thank you for reporting.
>
> In general I would suggest you to use a newer Apache KIE version, 8.44 is very old and no longer supported. Can you please doublecheck if the same reproduces with latest 10.2 version?
Thanks for pointing us at 10.2 — testing there turned out to be the thing that showed us we were holding it wrong.
**Short version: this is our bug, not yours.** Our KieBases are `sequential="true"`, and our generated rules were calling `update($ctx)` on a fact that other patterns bind via `from $ctx.…`. That's philosophically incoherent: sequential mode's whole contract is *insert once, fire in salience order, never re-evaluate*, and `update()` asks for exactly the re-evaluation that contract rules out. Because sequential mode builds `FromNode`s with `tupleMemoryEnabled=false`, the left-tuple memory is never allocated — and then the update/delete propagation paths dereference it. We were writing a forward-chaining idiom into an engine configuration that had opted out of forward chaining, and we'd been doing it 7,811 times across 5,225 DRLs without realizing it.
### What 10.x changed for us
8.44 tolerated the mistake almost completely; 10.2 does not. All numbers below are from the same ruleset and the same request, with each artifact compiled by the same KIE version that runs it:
| Scenario (`sequential="true"`) | 8.44.0.Final | 10.2.0 |
|---|---:|---:|
| Cold `KieContainer`, no incremental updates | pass | **fail, every run** |
| Chain of 4 in-place `updateToVersion()` upgrades | fails only at the last step | **fails from the 2nd step onward** |
| Same chain, `update($ctx)` removed (insert-only) | pass | **pass, 0 failures** |
| Cold container, `sequential=false`, `update()` kept | pass | **pass** |
Two failure signatures showed up on 10.2 depending on which path was hit first:
```
NPE: DoubleLinkedEntry.getPrevious() is null
at org.drools.core.util.LinkedList.remove(LinkedList.java:178)
at org.drools.core.util.index.TupleList.remove(TupleList.java:51)
at org.drools.core.phreak.PhreakFromNode.doLeftDeletes(PhreakFromNode.java:207)
```
```
NPE: "previousMatches" is null
at org.drools.core.phreak.PhreakFromNode.doLeftUpdates(PhreakFromNode.java:163)
```
The second one is the same NPE 8.44 produced (at `:154` there). So 10.2 didn't introduce a new defect so much as stop hiding an existing misuse — on 8.44 it took accumulated incremental-update history to surface; on 10.2 a first-load container trips it immediately. Removing `update($ctx)` entirely fixes it on **both** versions, and we're keeping `sequential="true"`.
### Feature request: make this misuse detectable
The reason this survived years in production is that **nothing anywhere told us.** It compiles clean on 8.44 and 10.2 — zero errors, zero warnings — and then fails at runtime as an NPE deep inside internal linked-list structures, which points nowhere near the actual mistake. Three things would each have saved us the entire investigation:
1. **Build-time validation (most valuable).** When a `KieBase` is `sequential`, have `KieBuilder` emit a warning — or an opt-in error — for any rule whose RHS calls `update()`/`modify()` on a fact bound through `from`. This is statically detectable at compile time, and it's unambiguously a bug in every case we can construct. Even a plain warning would have caught it on day one.
2. **A guard with a real message.** Where the code currently dereferences the un-allocated tuple memory, a null check that throws something like `"update()/modify() is not supported for from-bound facts in a sequential KieBase — rule X"` would turn a 200-frame internal NPE into a self-explaining error.
3. **A documentation note.** The sequential-mode docs describe the performance characteristics but don't state that RHS fact mutation is incompatible with it. `update($ctx)` is idiomatic Drools in every tutorial; it isn't obvious that it's invalid specifically under `sequential="true"`.
Happy to open a separate issue for any of these, or to test a patch — we have the full reproduction environment and can bisect or instrument on request.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [I] Drools PhreakFromNode NPE 8.44.0.Final [incubator-kie]
Posted by "tkobayas (via GitHub)" <gi...@apache.org>.
tkobayas commented on issue #7125:
URL: https://github.com/apache/incubator-kie/issues/7125#issuecomment-6511877959
Hi @vamsizzz, sorry for the confusion regarding the sequential + update scenario.
As explained in https://github.com/apache/incubator-kie/issues/7201, using `update()` in sequential mode is intended to work, but this behavior was not documented (so it's understandable that users might consider it incorrect usage). There was also a bug in this scenario, which you reported. The bug has been fixed by https://github.com/apache/incubator-kie/pull/7202, so this scenario will work without the NPE in the upcoming 10.3.0 release.
The expected behavior is:
- **Without update/modify in RHS**: All rules see the facts as they were at insertion time.
- **With update/modify in RHS**: Rules that have already fired are not re-evaluated. Rules that have not yet been evaluated see the updated values when their turn comes.
While the first scenario (without update/modify) remains the standard and more straightforward approach, the second scenario may be useful for certain use cases.
This behavior will also be documented in the 10.3 documentation (https://github.com/apache/incubator-kie-docs/pull/4604).
Thank you again for reporting this issue!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org