grafana/k6 · error
stack too big
Error message
stack too big
What it means
getPreviousRequiringFile() walks up to 1000 captured stack frames looking for the internal require wrapper frame ('(*requireImpl).require-fm') to identify the file that triggered a require (mostly for legacy open() semantics). If the stack reaches 1000 frames without finding it, k6 gives up with 'stack too big' rather than guessing the caller. This is an internal guard, not a normal user error.
Source
Thrown at js/modules/require_impl.go:217
func getPreviousRequiringFile(vu VU) (string, error) {
rt := vu.Runtime()
var buf [1000]sobek.StackFrame
frames := rt.CaptureCallStack(1000, buf[:0])
for i, frame := range frames[1:] { // first one should be the current require
// TODO have this precalculated automatically
if frame.FuncName() == "go.k6.io/k6/v2/internal/js.(*requireImpl).require-fm" {
// we need to get the one *before* but as we skip the first one the index matches ;)
result := frames[i].SrcName()
if result == "file:///-" {
return vu.InitEnv().CWD.JoinPath("./-").String(), nil
}
return result, nil
}
}
// hopefully nobody is calling `require` with 1000 big stack :crossedfingers:
if len(frames) == 1000 {
return "", errors.New("stack too big")
}
// fallback
result := frames[len(frames)-1].SrcName()
if result == "file:///-" {
return vu.InitEnv().CWD.JoinPath("./-").String(), nil
}
return result, nil
}
// sets the provided promise in such way as to ignore falures
// this is mostly needed as failures are handled separately and we do not want those to lead to stopping the event loop
func promisesThenIgnore(rt *sobek.Runtime, promise *sobek.Promise) {
call, _ := sobek.AssertFunction(rt.ToValue(promise).ToObject(rt).Get("then"))
handler := rt.ToValue(func(_ sobek.Value) {})
_, _ = call(rt.ToValue(promise), handler, handler)
}
View on GitHub (pinned to 93accf6570)
Solutions
- Hoist the require()/open() call to module top level instead of calling it deep in recursion
- Reduce recursion depth (convert to iteration or memoize) if the call site must stay nested
- If it reproduces with a reasonably shallow stack, report it as a k6 bug with the script
Example fix
// before (deep inside recursion)
function walk(n) { if (n === 0) { data = open('./f.json'); return; } walk(n - 1); }
// after (top level)
const data = open('./f.json');
function walk(n) { /* uses the preloaded data */ } Defensive patterns
Strategy: try-catch
Try / catch
// in JS: hoist open()/require() to top level so this internal guard never triggers; // in Go callers of getPreviousRequiringFile, treat the error as non-fatal and fall back to a known file.
Prevention
- Call open() and require() at module top level, not deep in recursion
- Convert deep recursion to iteration when it must load files
- Report reproducible cases with shallow stacks as k6 bugs
When it happens
Trigger: Calling require()/open() from inside ~1000-deep recursion or a very long call chain, so the wrapper frame falls outside the 1000-frame window captured by rt.CaptureCallStack(1000, ...).
Common situations: Deeply recursive helper functions that eventually require() or open() a file; machine-generated scripts with enormous call chains; bundler output that inlines huge module trees. Extremely rare in practice.
Related errors
- CommonJS's exports must not be null
- require() can't be used with an empty specifier
- Error while parsing selector `${selector}` - selector cannot
- k6/experimental/redis has been removed. Please migrate to th
- k6/experimental/browser has been graduated, please use k6/br
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/74966815810372ab.
Report an issue: GitHub.