grafana/k6 · error

SharedArray constructor does not support async functions as

Error message

SharedArray constructor does not support async functions as second argument

What it means

SharedArray serializes the builder function's return value once, synchronously, during the init context. An async builder would return a Promise that cannot be serialized and shared, so data.go:87-90 rejects async functions with asyncFunctionNotSupportedMsg.

Source

Thrown at internal/js/modules/k6/data/data.go:88

const asyncFunctionNotSupportedMsg = "SharedArray constructor does not support async functions as second argument"

// sharedArray is a constructor returning a shareable read-only array
// indentified by the name and having their contents be whatever the call returns
func (d *Data) sharedArray(call sobek.ConstructorCall) *sobek.Object {
	rt := d.vu.Runtime()

	if d.vu.State() != nil {
		common.Throw(rt, errors.New("new SharedArray must be called in the init context"))
	}

	name := call.Argument(0).String()
	if name == "" {
		common.Throw(rt, errors.New("empty name provided to SharedArray's constructor"))
	}
	val := call.Argument(1)

	if common.IsAsyncFunction(rt, val) {
		common.Throw(rt, errors.New(asyncFunctionNotSupportedMsg))
	}

	fn, ok := sobek.AssertFunction(val)
	if !ok {
		common.Throw(rt, errors.New("a function is expected as the second argument of SharedArray's constructor"))
	}

	builder := func() (sharedArray, error) { return getSharedArrayFromCall(rt, fn) }
	array, err := d.shared.loadOrStore(name, builder)
	if err != nil {
		common.Throw(rt, err)
	}

	return array.wrap(rt).ToObject(rt)
}

// RecordReader is the interface that wraps the action of reading records from a resource.
//

View on GitHub (pinned to 93accf6570)

Solutions

  1. Make the builder synchronous: precompute data at init time (e.g. JSON.parse(open('data.json'))) and return it from a plain function
  2. Remove every await/async from the builder; do any async work elsewhere and pass results in
  3. If async data loading is unavoidable, load it before the constructor call site at top level and wrap the final plain array

Example fix

// before
new SharedArray('users', async () => {
  return JSON.parse(open('./users.json')); // async -> rejected
});

// after
const users = JSON.parse(open('./users.json'));
new SharedArray('users', function () { return users; });
Defensive patterns

Strategy: validation

Validate before calling

// Static discipline: ensure the builder is not declared async and contains no await.
// Load data synchronously at init, then wrap:
const rows = JSON.parse(open('./rows.json'));
new SharedArray('rows', function () { return rows; });

Prevention

When it happens

Trigger: new SharedArray('x', async () => [...]); a builder that awaits something (file reads, fetches, timers) — anything declared with async or returning a Promise.

Common situations: Copying async open()/readFile patterns from k6/experimental modules into SharedArray builders; attempting HTTP calls or async I/O during init; refactors that add await inside the builder.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/6a7c6a3ce7ad90eb. Report an issue: GitHub.