grafana/k6 · error
open() can't be used with files that weren't previously open
Error message
open() can't be used with files that weren't previously opened during initialization (__VU==0), path: %q
What it means
During init, k6 wraps the filesystem so only files actually opened at init are cached; in the VU stage open() is served from that cache (allowOnlyOpenedFiles / fsext.OnlyCachedEnabler in internal/js/initcontext.go). When a VU requests a path the cache has never seen, fsext returns ErrPathNeverRequestedBefore and readFile rewrites it into this error. The rule: every file must be opened unconditionally during initialization (__VU==0) so k6 can snapshot it for all VUs.
Source
Thrown at internal/js/initcontext.go:42
filename = strings.TrimPrefix(filename, "file://")
data, err := readFile(fs, fsext.Abs(basePWD.Path, filename))
if err != nil {
return nil, err
}
if len(args) > 0 && args[0] == "b" {
ab := rt.NewArrayBuffer(data)
return rt.ToValue(&ab), nil
}
return rt.ToValue(string(data)), nil
}
func readFile(fileSystem fsext.Fs, filename string) (data []byte, err error) {
defer func() {
if errors.Is(err, fsext.ErrPathNeverRequestedBefore) {
// loading different files per VU is not supported, so all files should are going
// to be used inside the scenario should be opened during the init step (without any conditions)
err = fmt.Errorf(
"open() can't be used with files that weren't previously opened during initialization (__VU==0), path: %q",
filename,
)
}
}()
// Workaround for https://github.com/spf13/fsext/issues/201
if isDir, err := fsext.IsDir(fileSystem, filename); err != nil {
return nil, err
} else if isDir {
return nil, fmt.Errorf("open() can't be used with directories, path: %q", filename)
}
return fsext.ReadFile(fileSystem, filename)
}
// allowOnlyOpenedFiles enables seen only files
func allowOnlyOpenedFiles(fs fsext.Fs) {View on GitHub (pinned to 93accf6570)
Solutions
- Open every candidate file unconditionally at the top level during init - even files only some VUs use - and select among the loaded contents later
- For structured data, load and parse at init (SharedArray for large datasets) instead of calling open() in the VU
- If data is truly per-VU and huge, pre-generate one combined file or split the run into multiple scripts
Example fix
// before: per-VU path -> file never cached during init
export default function () {
const data = JSON.parse(open(`./data/${__VU}.json`));
}
// after: open all files unconditionally at init, then pick per VU
import { SharedArray } from 'k6/data';
const shards = new SharedArray('shards', () => [
JSON.parse(open('./data/1.json')),
JSON.parse(open('./data/2.json')),
]);
export default function () {
const data = shards[(__VU - 1) % shards.length];
} Defensive patterns
Strategy: validation
Validate before calling
# heuristic: flag dynamic/interpolated paths inside open() - they cannot all be cached at init
grep -nP 'open\(\s*[`'"'"'].*\$\{|open\(.*\+' script.js && \
echo 'warning: dynamic open() path - open every file unconditionally during init instead' Prevention
- Open every file the test may use unconditionally at the top level, even conditionally-needed ones
- Never build open() paths from __VU or __ITER
- Load data at init (SharedArray) instead of opening files inside iterations
When it happens
Trigger: Opening a per-VU path such as open(`data_${__VU}.json`) inside the default function; opening file A during init only under a condition (if (__ENV.MODE) open('a.csv')) so a different path is requested later; calling open() in the VU stage on a path never touched at init.
Common situations: Sharding test data per VU; environment-dependent fixtures; code that opens a fallback file only on some branches; loading different files per iteration.
Related errors
- the "open" function is only available in the init stage (i.e
- open() can't be used with directories, path: %q
- open() can't be used with an empty filename
- error parsing script options: %w
- the "require" function is only available in the init stage (
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/1d8d928ddb73426e.
Report an issue: GitHub.