{"record":{"id":"30eaa7340daeeeef","repo":"grafana/k6","slug":"executor-s-function-s-not-found-in-exports","errorCode":null,"errorMessage":"executor %s: function '%s' not found in exports","messagePattern":"executor (.+?): function '(.+?)' not found in exports","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/config.go","lineNumber":359,"sourceCode":"}\n\nfunc consolidateErrorMessage(errList []error, title string) error {\n\tif len(errList) == 0 {\n\t\treturn nil\n\t}\n\n\terrMsgParts := []string{title}\n\tfor _, err := range errList {\n\t\terrMsgParts = append(errMsgParts, fmt.Sprintf(\"\\t- %s\", err.Error()))\n\t}\n\n\treturn errors.New(strings.Join(errMsgParts, \"\\n\"))\n}\n\nfunc validateScenarioConfig(conf lib.ExecutorConfig, isExecutable func(string) bool) error {\n\texecFn := conf.GetExec()\n\tif !isExecutable(execFn) {\n\t\treturn fmt.Errorf(\"executor %s: function '%s' not found in exports\", conf.GetName(), execFn)\n\t}\n\treturn nil\n}\n","sourceCodeStart":341,"sourceCodeEnd":363,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cmd/config.go#L341-L363","documentation":"Produced by validateScenarioConfig during options validation: every scenario/executor config has an `exec` field naming the exported function it should call, and that name is checked against the script's actual exports via the isExecutable predicate. If the scenario's exec value is not among the exported functions (the default-export object's keys), k6 refuses to run because the executor would have nothing to call.","triggerScenarios":"Setting options.scenarios.<name>.exec (in the script, CLI --scenario-*/--exec flags, config file, or env K6_* scenario options) to a function that is not exported: `export default { orders: fn }` with `exec: 'order'` (typo), or `exec: 'default'` when only a default function export exists and the named export is missing; also when scenario options come from an external config file that diverges from the script.","commonSituations":"Renaming a function in the script but not in scenario options; copy-pasting options between scripts whose exports differ; driving scenarios purely via CLI/config (k6 run --config) where exec references drift from the archive's exports; the error message lists all invalid execs per scenario under a title in the aggregated validation error.","solutions":["Check the error's per-scenario lines: they name the executor and the exact missing function","Fix the exec value to match a key of the script's `export default { ... }` object exactly (case-sensitive)","Export the intended function: `export default { myfn }` and use `exec: 'myfn'`","If the function is only the default export, use exec: 'default' (the implicit default function name)"],"exampleFix":"// before\nexport default function () { /* ... */ }\nexport const options = { scenarios: { s1: { executor: 'per-vu-iterations', exec: 'login' } } };\n// error: executor s1: function 'login' not found in exports\n\n// after\nexport function login() { /* ... */ }\nexport default { login };\nexport const options = { scenarios: { s1: { executor: 'per-vu-iterations', exec: 'login' } } };","handlingStrategy":"validation","validationCode":"// In-script guard: assert every scenario exec exists in exports before k6 validates\nconst exports = { login, checkout };\nfor (const [name, sc] of Object.entries(options.scenarios ?? {})) {\n  if (!(sc.exec ?? 'default') in exports && sc.exec !== 'default') {\n    throw new Error(`scenario ${name}: exec '${sc.exec}' not exported`);\n  }\n}\nexport default exports;","typeGuard":"function scenarioExecExists(scenario, exported) {\n  const fn = scenario.exec ?? 'default';\n  return fn === 'default' || Object.prototype.hasOwnProperty.call(exported, fn);\n}","tryCatchPattern":null,"preventionTips":["Derive scenario exec names from the export object keys, never free-typed strings","Add a smoke `k6 inspect script.js` step in CI — it runs scenario validation without executing load","When renaming a function, grep the whole repo for the old name including options blocks"],"tags":["scenarios","options","exports","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}