grafana/k6 · error
exported 'teardown' must be a function
Error message
exported 'teardown' must be a function
What it means
Same export scan as `setup`: k6 requires an export named `teardown` to be a callable function so it can run it once after all iterations. A non-function teardown binding is rejected during bundle loading (bundle.go:227).
Source
Thrown at internal/js/bundle.go:227
dec.DisallowUnknownFields()
if err = dec.Decode(&b.Options); err != nil {
if uerr := json.Unmarshal(data, &b.Options); uerr != nil {
// Beautify the error so we can try to show the user the key and potential value that is failing to parse
uerr = beautifyOptionsJSONUnmarshalError(data, uerr)
err = errext.WithAbortReasonIfNone(
errext.WithExitCodeIfNone(uerr, exitcodes.InvalidConfig),
errext.AbortedByScriptError,
)
return
}
b.preInitState.Logger.WithError(err).Warn("There were unknown fields in the options exported in the script")
err = nil
}
case consts.SetupFn:
err = errors.New("exported 'setup' must be a function")
return
case consts.TeardownFn:
err = errors.New("exported 'teardown' must be a function")
return
}
}
})
<-ch
if err != nil {
return err
}
if len(b.callableExports) == 0 {
return errors.New("no exported functions in script")
}
return nil
}
func beautifyOptionsJSONUnmarshalError(data []byte, err error) error {
unmarshalTypError := new(json.UnmarshalTypeError)View on GitHub (pinned to 93accf6570)
Solutions
- Declare it as a function: `export function teardown() { ... }`
- To conditionally skip teardown, remove the export or guard inside the function instead of exporting a boolean
- Rename unrelated data exports away from the reserved name
Example fix
// before
export const teardown = false;
// after
export function teardown(data) { if (!data) return; /* cleanup */ } Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof teardown !== 'undefined' && typeof teardown !== 'function') { throw new Error('teardown export must be a function'); } Type guard
const isValidTeardown = (v) => v === undefined || typeof v === 'function';
Prevention
- Never use `export const teardown = false` as a toggle — just remove the export
- Reserve the names setup/teardown exclusively for lifecycle functions
- CI-lint for non-function exports named teardown
When it happens
Trigger: `export const teardown = true`, `export let teardown = {}`, or importing and re-exporting a non-function value under the name `teardown` in the entry script.
Common situations: Feature-flag objects like `export const teardown = false` meant to disable teardown; refactors that changed teardown into data; typos such as `teardownFn`.
Related errors
- exported 'setup' must be a function
- no exported functions in script
- no gRPC connection, you must call connect first
- open() can't be used with an empty filename
- predicate function is not callable
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/85fa7b75e9ec4d77.
Report an issue: GitHub.