{"record":{"id":"68ca62cb445740cd","repo":"grafana/k6","slug":"no-exported-functions-in-script","errorCode":null,"errorMessage":"no exported functions in script","messagePattern":"no exported functions in script","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/bundle.go","lineNumber":238,"sourceCode":"\t\t\t\t\tb.preInitState.Logger.WithError(err).Warn(\"There were unknown fields in the options exported in the script\")\n\t\t\t\t\terr = nil\n\t\t\t\t}\n\t\t\tcase consts.SetupFn:\n\t\t\t\terr = errors.New(\"exported 'setup' must be a function\")\n\t\t\t\treturn\n\t\t\tcase consts.TeardownFn:\n\t\t\t\terr = errors.New(\"exported 'teardown' must be a function\")\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t})\n\t<-ch\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(b.callableExports) == 0 {\n\t\treturn errors.New(\"no exported functions in script\")\n\t}\n\n\treturn nil\n}\n\nfunc beautifyOptionsJSONUnmarshalError(data []byte, err error) error {\n\tunmarshalTypError := new(json.UnmarshalTypeError)\n\tif errors.As(err, &unmarshalTypError) {\n\t\te := unmarshalTypError\n\t\tpreviousNewLineIndex := max(bytes.LastIndexByte(data[:e.Offset], '\\n'), 0)\n\t\tnextNewLineIndex := max(min(bytes.IndexByte(data[e.Offset:], '\\n'), len(data)-1), (int)(e.Offset))\n\n\t\tinfo := strings.TrimSpace(string(data[previousNewLineIndex:nextNewLineIndex]))\n\t\terr = fmt.Errorf(\"parsing options from script got error while parsing %q: %w\", info, e)\n\t}\n\treturn err\n}\n","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/bundle.go#L220-L256","documentation":"After the export scan, the bundle found zero callable exports (b.callableExports is empty). k6 executes at least one exported function per iteration — normally the default function — so a script with no exported functions has nothing to run.","triggerScenarios":"A script exporting only `options` (or other constants) with no `export default function`; helper/util modules mistakenly passed to `k6 run` as the entry script.","commonSituations":"Options-only snippets saved as a script; refactors that wrapped the default function in a const without exporting it; running a shared library file directly.","solutions":["Add a default function: `export default function () { /* test logic */ }`","If the file is really a helper module, point `k6 run` at the actual entry script instead","For scenarios-only configs, still export an (empty) default function so iterations exist"],"exampleFix":"// before\nexport const options = { vus: 1, duration: '10s' };\n\n// after\nexport const options = { vus: 1, duration: '10s' };\nexport default function () { http.get('https://test.k6.io'); }","handlingStrategy":"validation","validationCode":"// entry-script guard: fail loudly if nothing is runnable\nlet hasDefault = false;\ntry { hasDefault = typeof module_default === 'function'; } catch (_) {}\n// simpler: ensure the file literally contains 'export default function' before shipping\ncurl -s script.js | grep -q 'export default function' || echo 'WARN: no default export' >&2","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Every entry script must `export default function` — even an empty one","Keep helper modules in a separate directory from entry scripts to avoid running them directly","Add a CI check that greps the entry file for a default export before `k6 run`"],"tags":["javascript","script-structure","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}