grafana/k6 · error

csv Parser constructor must be called in the init context

Error message

csv Parser constructor must be called in the init context

What it means

The experimental CSV module (k6/experimental/csv) parses files that were opened in the init context; its Parser constructor therefore refuses to run once a VU state exists. Like SharedArray and grpc client.load, it is an init-only API by design, because file descriptors cannot be shared across VU iterations.

Solutions

  1. Move 'new CSV.Parser(...)' to the top level of the script, next to the open() call, and export/reference it from the VU function.
  2. If rows must be parsed per-VU conditionally, keep one top-level parser and consume it selectively inside the default function.
  3. Ensure open() for the CSV file is also in the init context - it is a prerequisite of the constructor anyway.

Example fix

// before
import CSV from 'k6/experimental/csv';
export default function () {
  const parser = new CSV.Parser(open('./data.csv')); // throws
}

// after
import CSV from 'k6/experimental/csv';
const parser = new CSV.Parser(open('./data.csv'), { delimiter: ',' });
export default function () { /* parser.readLine() here */ }
Defensive patterns

Strategy: validation

Validate before calling

// Parser construction belongs at module top level
const parser = new CSV.Parser(open('./data.csv'), { delimiter: ',' });
export default function () { /* consume parser here */ }

Prevention

When it happens

Trigger: 'new CSV.Parser(...)' executed inside export default function(), setup(), or any runtime-called helper - i.e. when mi.vu.State() != nil. Constructing it at module top level works.

Common situations: Opening the CSV lazily inside the default function to 'avoid paying parse cost when unused'; wrapping parser creation in a function called per iteration; upgrading scripts from older examples that parsed CSV manually inside the VU with sharedArray.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/00312a5789d9d634. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/experimental/csv/module.go:155

			callback(func() error {
				return reject(rt.NewGoError(err))
			})
			return
		}
		callback(func() error {
			return resolve(fn())
		})
	}()

	return promise, nil
}

// NewParser creates a new CSV parser instance.
func (mi *ModuleInstance) NewParser(call sobek.ConstructorCall) *sobek.Object {
	rt := mi.vu.Runtime()

	if mi.vu.State() != nil {
		common.Throw(rt, errors.New("csv Parser constructor must be called in the init context"))
	}

	if len(call.Arguments) < 1 || sobek.IsUndefined(call.Argument(0)) {
		common.Throw(rt, fmt.Errorf("csv Parser constructor takes at least one non-nil source argument"))
	}

	fileArg := call.Argument(0)
	if common.IsNullish(fileArg) {
		common.Throw(rt, fmt.Errorf("csv Parser constructor takes at least one non-nil source argument"))
	}

	// 1. Make sure the Sobek object is a fs.File (Sobek operation)
	var file fs.File
	if err := mi.vu.Runtime().ExportTo(fileArg, &file); err != nil {
		common.Throw(
			mi.vu.Runtime(),
			fmt.Errorf("first argument expected to be a fs.File instance, got %T instead", call.Argument(0)),
		)

View on GitHub (pinned to 01ffac6f24)