Skip to content

GET /api/v0/biomodel/{id}/biomodel.bngl returns 500 for any BioModel with zero applications #2079

Description

@jcschaff

Summary

GET /api/v0/biomodel/{id}/biomodel.bngl returns HTTP 500 with Index 0 out of bounds for length 0
for any BioModel that has zero applications. A model with no application is perfectly legal,
so this is a routine input reaching an unguarded array access and surfacing as a server error.

Reproduce

$ curl -s -o /dev/null -w '%{http_code}\n' \
    'https://vcell.cam.uchc.edu/api/v0/biomodel/321238605/biomodel.bngl'
500

$ curl -s 'https://vcell.cam.uchc.edu/api/v0/biomodel/321238605/biomodel.bngl'
status = (Index 0 out of bounds for length 0),
request = (GET http://vcell.cam.uchc.edu/api/v0/biomodel/321238605/biomodel.bngl HTTP/1.1),
response = (HTTP/1.1 - Internal Server Error (500) - Index 0 out of bounds for length 0)

Deterministic, not load-related. BioModel 321238605 (kartik-bm-new, public) reports
"applications": [].

Cause

BiomodelBNGLServerResource.java:118:

BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(biomodelVCML));
SimulationContext chosenSimContext = bioModel.getSimulationContext(0);   // <-- throws when there are none
RbmNetworkGenerator.writeBngl(chosenSimContext, pw, false, true);

With no simulation contexts, getSimulationContext(0) throws
ArrayIndexOutOfBoundsException, which the catch-all at the end of the method converts to
Status.SERVER_ERROR_INTERNAL.

Scope

The correlation is exact across a sample of six public models:

bmKey applications biomodel.bngl
321238605 0 500
320046667 1 200
320029568 1 200
316581880 4 200
315396932 1 200
315272981 1 200

It is not a rare shape: in the single listing GET /api/v0/biomodel?category=educational&maxRows=1000,
63 of 1000 models have zero applications, so every one of those 500s on this endpoint.

Suggested fix

Guard the empty case and return a client error that says what is wrong, rather than a 500 — e.g.
404 or 400 with "BioModel has no application; a BNGL export requires one". Two further points
worth deciding while in there:

  • Silently picking index 0 is itself questionable for a model with several applications
    (316581880 has 4). The caller has no way to choose, and no way to know which was exported.
  • The catch (Exception e) at the bottom maps every unexpected failure to a 500 carrying the raw
    exception message, which is how an ArrayIndexOutOfBoundsException ended up as user-facing API
    output.

How this surfaced

Found in the vcell-ai-rke-dev namespace, where the AI backend's vcelldb_service proxies to this
endpoint and logged four consecutive failures:

ERROR | vcelldb_service | HTTP error fetching BNGL file for biomodel 321238605:
  500 - status = (Index 0 out of bounds for length 0)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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