{"record":{"id":"5374a22a16ede8b9","repo":"grafana/k6","slug":"scenario-name-can-t-be-empty","errorCode":null,"errorMessage":"scenario name can't be empty","messagePattern":"scenario name can't be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/executor/base_config.go","lineNumber":54,"sourceCode":"\n\t// TODO: future extensions like distribution, others?\n}\n\n// NewBaseConfig returns a default base config with the default values\nfunc NewBaseConfig(name, configType string) BaseConfig {\n\treturn BaseConfig{\n\t\tName:         name,\n\t\tType:         configType,\n\t\tGracefulStop: types.NewNullDuration(DefaultGracefulStopValue, false),\n\t}\n}\n\n// Validate checks some basic things like present name, type, and a positive start time\nfunc (bc BaseConfig) Validate() (result []error) {\n\t// Some just-in-case checks, since those things are likely checked in other places or\n\t// even assigned by us:\n\tif bc.Name == \"\" {\n\t\tresult = append(result, errors.New(\"scenario name can't be empty\"))\n\t}\n\tif !scenarioNameWhitelist.MatchString(bc.Name) {\n\t\tresult = append(result, errors.New(scenarioNameErr))\n\t}\n\tif bc.Exec.Valid && bc.Exec.String == \"\" {\n\t\tresult = append(result, errors.New(\"exec value cannot be empty\"))\n\t}\n\tif bc.Type == \"\" {\n\t\tresult = append(result, errors.New(\"missing or empty type field\"))\n\t}\n\t// The actually reasonable checks:\n\tif bc.StartTime.Duration < 0 {\n\t\tresult = append(result, errors.New(\"the startTime can't be negative\"))\n\t}\n\tif bc.GracefulStop.Duration < 0 {\n\t\tresult = append(result, errors.New(\"the gracefulStop timeout can't be negative\"))\n\t}\n\treturn result","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/lib/executor/base_config.go#L36-L72","documentation":"BaseConfig.Validate() performs just-in-case sanity checks on every scenario config; the first is that the scenario's Name is non-empty. Scenario names come from the keys of the options.scenarios object (or programmatic construction), so an empty-string key produces an anonymous config that metrics labels and the REST API could not reference, and validation collects this error.","triggerScenarios":"Exporting options with scenarios: { '': { executor: 'shared-iterations', ... } }, or building a BaseConfig programmatically without setting Name before Validate().","commonSituations":"Generating scenarios from a config map/env prefix where one key is blank; YAML/JSON with an empty key; refactors that rename scenario keys and accidentally leave one empty; template strings producing '' as the key.","solutions":["Give every scenario a non-empty key: scenarios: { smoke: { executor: 'shared-iterations' } }","Filter empty keys when generating scenarios from data: Object.fromEntries(Object.entries(map).filter(([k]) => k))","If constructing BaseConfig in Go, always set Name (e.g. from the map key) before calling Validate()"],"exampleFix":"// before\nexport const options = { scenarios: { '': { executor: 'shared-iterations' } } };\n\n// after\nexport const options = { scenarios: { smoke: { executor: 'shared-iterations' } } };","handlingStrategy":"validation","validationCode":"// before exporting options, assert every scenario has a name\nfor (const name of Object.keys(scenarios)) {\n  if (!name) throw new Error('scenario name can\\u2019t be empty');\n}\nexport const options = { scenarios };","typeGuard":"const hasValidScenarioNames = (scenarios) =>\n  Object.keys(scenarios).every((k) => k.length > 0 && /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(k));","tryCatchPattern":null,"preventionTips":["Filter empty keys when generating scenarios from maps/env data","Use descriptive scenario names (smoke, load, soak) in every options block","In Go, always populate BaseConfig.Name before Validate()"],"tags":["config","scenarios","options","validation","startup"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}