Skip to content

Fix NPE in StochMathMapping for symbol-less rate expressions#1672

Merged
jcschaff merged 1 commit intomasterfrom
fix-stoch-math-mapping-getprobrate-npe
May 1, 2026
Merged

Fix NPE in StochMathMapping for symbol-less rate expressions#1672
jcschaff merged 1 commit intomasterfrom
fix-stoch-math-mapping-getprobrate-npe

Conversation

@jcschaff
Copy link
Copy Markdown
Member

Summary

  • One-line null-guard fix in StochMathMapping.getProbabilityRate(... GeneralKineticsStochasticFunction ...). Expression.getSymbols() is documented to return null when the expression has no free symbols (see Expression.java:545); the for-each at line 145 didn't guard for that, producing an NPE.
  • The corpus error signature is unambiguous: Cannot read the array length because "<local7>" is null at StochMathMapping.getProbabilityRate(StochMathMapping.java:145).
  • Fix mirrors the established null-guard pattern already used in AbstractStochMathMapping.getSubstitutedExpr (line 155).

Why now

Triage of a user-support-email log corpus identified this as the next-largest unaddressed cluster: 6 distinct user incidents, 25 stack traces, multiple distinct user models. Users currently see a deep NPE rather than a successful stochastic math generation.

Why this trips

The GeneralKineticsStochasticTransformer fallback is the intended path for non-mass-action rate laws (Michaelis-Menten, Hill, etc.) — it takes the authoritative reaction rate as a net flux and uses max(rate, 0) as the irreversible forward rate, which is exactly the right shape for stochastic simulation. The NPE was preventing that path from completing whenever the rate expression flattened to no free symbols (e.g. a constant rate, or a rate where all parameters and species have already been resolved upstream).

Diff

// vcell-core/.../StochMathMapping.java:142-146
 // collect symbolTableEntries for speciesContexts within netRateExpr and replace with concentration parameter
 netRateExpr = new Expression(netRateExpr);
-for (String symbol : netRateExpr.getSymbols()) {
+// Expression.getSymbols() returns null when the expression has no free symbols
+// (e.g. a constant rate, or a rate that only references already-resolved values).
+String[] symbols = netRateExpr.getSymbols();
+for (int i = 0; symbols != null && i < symbols.length; i++) {
+    String symbol = symbols[i];
     SymbolTableEntry symbolTableEntry = netRateExpr.getSymbolBinding(symbol);

Test plan

  • mvn compile -pl vcell-core -am — builds clean
  • mvn test -pl vcell-core -Dgroups="Fast" — same pass/fail count as master; only failure is the pre-existing unrelated VCellDataTest.test_3D Poetry environmental error
  • Manual: open a stochastic application with a non-mass-action reaction whose rate flattens to no free symbols and confirm math generation completes

🤖 Generated with Claude Code

…xpressions

`Expression.getSymbols()` is documented to return null when the expression
has no free symbols (see Expression.java:545). The general-kinetics path
in StochMathMapping was iterating over the result with an unguarded
for-each, producing an NPE whose corpus signature is:

    Cannot read the array length because "<local7>" is null
        at cbit.vcell.mapping.StochMathMapping.getProbabilityRate
            (StochMathMapping.java:145)

This trips when a non-mass-action rate expression flattens to a constant
or otherwise contains no free symbols (e.g. a Michaelis-Menten rate where
all parameters and species have already been resolved upstream). The fix
mirrors the established null-guard pattern already used in
AbstractStochMathMapping.getSubstitutedExpr (line 155).

The general-kinetics fallback in StochasticTransformer is the intended
path for non-mass-action kinetics — it takes the authoritative reaction
rate as a net flux and uses max(rate, 0) as the irreversible forward
rate, which is exactly the right shape for stochastic simulation. The
NPE was preventing that path from completing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jcschaff jcschaff requested a review from danv61 April 30, 2026 18:57
@jcschaff jcschaff merged commit f54c924 into master May 1, 2026
13 checks passed
@jcschaff jcschaff deleted the fix-stoch-math-mapping-getprobrate-npe branch May 1, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants