Skip to main content
Article

When the Script Mediator Error Is Not a Script Error: JSON Responses Too Large to Build

5 min read 42 views

An integration that reads a virtual machine inventory from vCenter worked on one instance and failed on the other. The error named the Script mediator, so the first assumption was a defect in the JavaScript. It was not. The response was simply too large for WSO2 Enterprise Integrator 6.6 to build, and the Script mediator happened to be the first thing that asked for it. This post describes how we found the actual cause, the three plausible theories we ruled out along the way, and the fix: making the response smaller instead of trying to raise a limit.

The symptom

ERROR {org.apache.synapse.mediators.bsf.ScriptMediator} - The script engine
returned an error executing the inlined js script function mediate
javax.script.ScriptException: Invalid JSON payload in <Unknown source> at line number 1

Everything in that message points at the script. But the Script mediator attaches the message payload to the script engine before the first statement of the script runs. The exception is raised while the payload is being built, not while the script is executing. A try/catch inside the script cannot catch it, and making the JavaScript more defensive changes nothing. We tried that first, and it did not work.

The body was also not malformed. The same request with curl, using the same session, returned well-formed JSON that parsed cleanly. That proves only that the body is valid JSON. It says nothing about whether EI can build it.

Finding the boundary

Measuring the response size for different requests against the failing instance gave a clear bracket:

RequestBody sizeResult
VMs on a single hosta few kilobytesbuilds
VMs filtered to powered offa little over 200 KBbuilds
All VMs, unfiltereda little over 300 KBfails

The unfiltered call on the smaller instance returned about half that and had always worked. So the limit lies somewhere between the largest response that built and the smallest that failed, a range that takes in 256 KB, which made a buffer boundary the obvious suspect. We did not pursue the exact parameter, because once the response was split it no longer mattered.

Three theories that each cost a run

An empty body

A 200 response with a zero-length body produces the same exception. vCenter replies with chunked transfer encoding and no Content-Length, so this was plausible. Measuring the body ruled it out.

Guarding the build with count()

The natural guard looks like this:

<filter xpath="count($body/*) > 0">

It breaks every call that was working. EI builds application/json lazily through its JSON stream builder, and an XPath count() in a filter does not expand the lazy element, so it counts zero on good responses too. A run that had read the full inventory read none, with no error. We would not use this guard on a JSON payload.

Compression

There is a proxy in front of vCenter, and every response carries vary: Accept-Encoding. With gzip requested, the large body shrinks to about a tenth of its size, so compression looked like a candidate: perhaps EI was asking for gzip and failing to decode it. But the small single-host response is compressed as well. If decompression were the problem, every call would fail, not only the large one. Ruled out.

The fix: partition the request

Rather than tune a limit we could not identify, we made each response smaller. For a VM listing, the natural partition is power state. Every VM has exactly one, so the union of the slices is the complete set, with nothing missed and nothing counted twice:

/api/vcenter/vm?power_states=POWERED_ON
/api/vcenter/vm?power_states=POWERED_OFF
/api/vcenter/vm?power_states=SUSPENDED

The partition can be checked arithmetically. The byte sizes of the three slices summed to exactly one byte less than the unfiltered call. The missing byte is the comma that joined the arrays. The VM counts summed to the full estate.

Two details matter in the implementation:

  • Collect all slices and process them once. Comparing each slice separately against the list of VMs already placed on hosts marked VMs from an earlier slice as unplaced.
  • An empty slice, typically SUSPENDED, returns []. That is a normal result, not a failure.

If a slice ever grows too large again, the next partition is by datacenter, because every VM belongs to exactly one.

Finding which call failed

The loop that drove these calls logged before each call, so the last log line named the call that had started, not the one whose response failed. That produced two wrong diagnoses, including accusing a host whose response turned out to be clean.

The fix was a temporary log line placed after the call and before anything touched the payload:

<log level="custom">
    <property name="STAGE" value="GET-PRE-BUILD"/>
    <property name="URL" expression="concat($ctx:HOST, $ctx:PATH)"/>
    <property name="HTTP_SC" expression="$ctx:HTTP_SC"/>
</log>

Then pair the last such line with the first error:

awk '/GET-PRE-BUILD/{last=$0} /ScriptMediator/{print last; print $0; exit}' wso2carbon.log

That named the failing URL on the first run. It is an instrument for diagnosis, not production logging, and it came out once the URL was known.

Conclusion

When an EI error names a mediator, ask whether the failure happened inside that mediator or in the payload it requested. A Script mediator that fails before its first statement is a build failure, and a build failure on a large, well-formed response is a size problem. The robust answer is to make the response smaller in a way you can verify, so the fix does not depend on a limit nobody has documented.

Our WSO2 course covers integrating large REST APIs and diagnosing failures like this one, taught by practitioners who do this work for a living.

K

Kofi Boateng

Related Articles

Article Info

Type
Article
Category
Enterprise Integration
Published
03 Oct 2026
Reading time
5 min

Search

Put this into practice

Our structured courses take these topics from article to hands-on skill, taught by the practitioners who write them.

Browse Courses