Skip to content

ArrayIndexOutOfBoundsException #61

Description

@anastasiasanto

Environment

  • COMETS 2.12.3 and 2.12.4 (also present in the current development branch as of this check)
  • Multi-species layout, models loaded via cometspy from SBML (cobrapy)

Description

COMETS crashes with:

ArrayIndexOutOfBoundsException: Index N out of bounds for length M

when the community's organisms have exchange-reaction (EX_) arrays of
different sizes. In our case: 4 organisms with 105 / 135 / 138 / 159 exchange
reactions respectively — the crash reports an index around 105-159, matching
the smallest/largest organism's array length.

Root cause (as far as we could trace it)

In FBACell.java, around the model-run loop (~line 1199 in 2.12.3), COMETS
indexes into an organism's local exchange-reaction array using an index
derived from the shared/global metabolite index of the whole simulated
world (i.e., the union of exchange metabolites across all community members).

The bounds check only verifies the index is valid within the global world
(kIndexInModel > -1) but does not also check that it is smaller than
the length of the current organism's own local array
(kIndexInModel < localArray.length). When an organism's exchange array is
smaller than another community member's (e.g. because its GEM simply has
fewer transporters/exchanges annotated), any global index that falls beyond
that organism's own array length triggers the out-of-bounds access.

Steps to reproduce (general pattern)

  1. Build a COMETS layout with ≥2 organisms whose SBML models have a
    different number of EX_ (boundary/exchange) reactions.
  2. Open all exchanges (cometspy's model.open_exchanges(), or equivalent
    direct bound-setting) so every organism can, in principle, exchange every
    metabolite present anywhere in the shared medium.
  3. Run a multi-cycle simulation with all organisms co-located (cross-feeding
    scenario). The crash is not immediate — it depends on which global
    metabolite index gets processed for which organism's cell during a given
    cycle, so it can appear intermittently rather than on cycle 1.

Workaround we are currently using

We equalize the exchange-reaction array size across all community members
before the run, by adding "padding" exchange reactions (copied from another
community member, for the metabolites a given organism doesn't already have)
to the SBML model of every organism with fewer exchanges than the largest.
This avoids the crash entirely, since every organism's local array is then
at least as long as any global index that can occur. (We do not lock the
padding bounds to zero — we let them fall under COMETS's defaultVmax/
defaultKm, since some of them turned out to correspond to genuinely
existing transporters in the model that were simply missing their boundary
EX_ reaction.)

Suggested fix

Add the missing bounds check (kIndexInModel < localArray.length) at the
indexing site in FBACell.java, or — more robustly — pad every organism's
internal exchange-reaction array to the size of the community-wide metabolite
index space at model-load time, so no per-cycle index can ever exceed a local
array's bounds.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions