The BMDB nightly gate has failed every night since 2026-08-31 (last green: run
33298492096). Each failure is real in the sense that a result differed from the baseline —
but the same models keep changing their minds, so accepting a baseline clears the signal
for a night and not longer.
What the last seven nightlies actually did
| model |
behaviour |
BIOMD0000001065 |
deviated (PASSED) on six of seven nights; matched its FAIL baseline once, on 09-06 |
BIOMD0000000547 |
MATH_GENERATION_FAILURE on 09-04/05/06/07; SOLVER_FAILURE on 08-31, 09-01, 09-03 |
BIOMD0000000613 |
MATH_GENERATION_FAILURE on 09-03/05/06/07; DIVIDE_BY_ZERO on 09-04 |
BIOMD0000000457 |
flipped PASSED → SOLVER_FAILURE on 09-05 only, and came back |
Note the 08-30 pass and the 08-31 failure are on the same commit (f0bb594443), which
is what rules out a code change as the cause.
Two of them are numerically borderline, and that is expected
The recorded failures say so:
- 1065 —
CV_REPTD_RHSFUNC_ERR ... pow(u,v) and u=-0.000000<0 and v=2.619640 not an integer, with EN_0_0 = -0.000000. A quantity sitting on zero, and pow of it is only
defined if the last bit lands positive.
- 547 —
At t = 8.09814e-18, mxstep steps taken before reaching tout. The solver
stalling at a denormal-scale step.
Nothing about VCell is going to make those two deterministic; they are models balanced on a
knife edge, and the right treatment is probably to stop gating on them rather than to fix
them.
BIOMD0000000613 is different, and is the reason for this issue
It is not arithmetic. It alternates between two failures two phases apart, both about
the same initial condition:
|
raised where |
message |
| some nights |
writing the solver input |
divide by zero '(M_initConc / OC_initConc)' |
| other nights |
math generation |
Initial condition for variable 'M' references variable 'L'. Initial conditions cannot reference variables. |
In one run the initial condition has been hoisted to the global parameter M_initConc
(SBMLImporter.hoistInitialConditionToGlobalParameter), which then divides by zero. In the
other it still holds a reference to species L, which Equation.checkInitialCondition
rejects outright.
That is the same model, the same input, and the same code producing two structurally
different MathDescriptions.
Correction (see the investigation comment below). I first read this as
ordering-dependent math generation. Running the model ten times in ten separate JVMs
gives the same answer every time, and identity hash codes differ on every JVM start —
so per-run hash ordering is not the mechanism. The variation is between environments, not
between runs, and the leading candidate is now the nightly's nightly-rebuilt Docker
image.
BIOMD0000000547 moving from SOLVER_FAILURE to MATH_GENERATION_FAILURE fits the same
shape: on some runs it reaches the solver, on others math generation refuses it first, with
the same checkInitialCondition message.
Suggested next steps
- Find the ordering dependence. Running 613 and 547 through math generation repeatedly
in one JVM, and across JVMs, should reproduce it without needing the nightly.
- Decide what to do about the knife-edge cases. The baseline can say
PASS, FAIL or
SKIP, and none of those means "either outcome is fine". Options: mark 1065 and 547
SKIP with the reason recorded, the way the workflow's 11 slow models already are; or
give the baseline a way to accept a set of outcomes.
Today's three deviations are accepted in #2078 so the signal is clear again, with the
reasoning recorded in the commit.
The BMDB nightly gate has failed every night since 2026-08-31 (last green: run
33298492096). Each failure is real in the sense that a result differed from the baseline —but the same models keep changing their minds, so accepting a baseline clears the signal
for a night and not longer.
What the last seven nightlies actually did
BIOMD0000001065FAILbaseline once, on 09-06BIOMD0000000547MATH_GENERATION_FAILUREon 09-04/05/06/07;SOLVER_FAILUREon 08-31, 09-01, 09-03BIOMD0000000613MATH_GENERATION_FAILUREon 09-03/05/06/07;DIVIDE_BY_ZEROon 09-04BIOMD0000000457PASSED→SOLVER_FAILUREon 09-05 only, and came backNote the 08-30 pass and the 08-31 failure are on the same commit (
f0bb594443), whichis what rules out a code change as the cause.
Two of them are numerically borderline, and that is expected
The recorded failures say so:
CV_REPTD_RHSFUNC_ERR ... pow(u,v) and u=-0.000000<0 and v=2.619640 not an integer, withEN_0_0 = -0.000000. A quantity sitting on zero, andpowof it is onlydefined if the last bit lands positive.
At t = 8.09814e-18, mxstep steps taken before reaching tout. The solverstalling at a denormal-scale step.
Nothing about VCell is going to make those two deterministic; they are models balanced on a
knife edge, and the right treatment is probably to stop gating on them rather than to fix
them.
BIOMD0000000613 is different, and is the reason for this issue
It is not arithmetic. It alternates between two failures two phases apart, both about
the same initial condition:
divide by zero '(M_initConc / OC_initConc)'Initial condition for variable 'M' references variable 'L'. Initial conditions cannot reference variables.In one run the initial condition has been hoisted to the global parameter
M_initConc(
SBMLImporter.hoistInitialConditionToGlobalParameter), which then divides by zero. In theother it still holds a reference to species
L, whichEquation.checkInitialConditionrejects outright.
That is the same model, the same input, and the same code producing two structurally
different
MathDescriptions.BIOMD0000000547moving fromSOLVER_FAILUREtoMATH_GENERATION_FAILUREfits the sameshape: on some runs it reaches the solver, on others math generation refuses it first, with
the same
checkInitialConditionmessage.Suggested next steps
in one JVM, and across JVMs, should reproduce it without needing the nightly.
PASS,FAILorSKIP, and none of those means "either outcome is fine". Options: mark 1065 and 547SKIPwith the reason recorded, the way the workflow's 11 slow models already are; orgive the baseline a way to accept a set of outcomes.
Today's three deviations are accepted in #2078 so the signal is clear again, with the
reasoning recorded in the commit.