grafana/k6 · error
missing or empty type field
Error message
missing or empty type field
What it means
Emitted by BaseConfig.Validate (lib/executor/base_config.go:62-64) when the scenario's executor/type field is empty. The type (JSON key 'executor', line 29) selects the execution strategy (constant-vus, ramping-vus, constant-arrival-rate, ramping-arrival-rate, shared-iterations, per-vu-iterations); k6 cannot instantiate an executor without it. Note Validate() only reports a missing type at this base level — an unknown type string fails earlier during unmarshaling in lib/executor.Decode.
Source
Thrown at lib/executor/base_config.go:63
GracefulStop: types.NewNullDuration(DefaultGracefulStopValue, false),
}
}
// Validate checks some basic things like present name, type, and a positive start time
func (bc BaseConfig) Validate() (result []error) {
// Some just-in-case checks, since those things are likely checked in other places or
// even assigned by us:
if bc.Name == "" {
result = append(result, errors.New("scenario name can't be empty"))
}
if !scenarioNameWhitelist.MatchString(bc.Name) {
result = append(result, errors.New(scenarioNameErr))
}
if bc.Exec.Valid && bc.Exec.String == "" {
result = append(result, errors.New("exec value cannot be empty"))
}
if bc.Type == "" {
result = append(result, errors.New("missing or empty type field"))
}
// The actually reasonable checks:
if bc.StartTime.Duration < 0 {
result = append(result, errors.New("the startTime can't be negative"))
}
if bc.GracefulStop.Duration < 0 {
result = append(result, errors.New("the gracefulStop timeout can't be negative"))
}
return result
}
// GetName returns the name of the scenario.
func (bc BaseConfig) GetName() string {
return bc.Name
}
// GetType returns the executor's type as a string ID.
func (bc BaseConfig) GetType() string {View on GitHub (pinned to 93accf6570)
Solutions
- Add an explicit executor field, e.g. executor: 'constant-vus' with vus and duration
- Pick the executor matching intent: shared-iterations, per-vu-iterations, constant-arrival-rate, ramping-arrival-rate, constant-vus, ramping-vus
Example fix
// before
export const options = {
scenarios: {
smoke: { vus: 1, duration: '10s' },
},
};
// after
export const options = {
scenarios: {
smoke: { executor: 'constant-vus', vus: 1, duration: '10s' },
},
}; Defensive patterns
Strategy: validation
Validate before calling
const VALID = new Set(['shared-iterations','per-vu-iterations','constant-vus','ramping-vus','constant-arrival-rate','ramping-arrival-rate']);
for (const [name, cfg] of Object.entries(options.scenarios || {})) {
if (!VALID.has(cfg.executor)) throw new Error(`scenario ${name}: missing/unknown executor`);
} Prevention
- Always start a scenario block by choosing the executor first, then fill its specific options
- Keep the k6 scenarios docs table handy: each executor has required fields (vus/duration vs startRate/stages)
When it happens
Trigger: Defining options.scenarios = { smoke: { vus: 1, duration: '10s' } } without an executor key, or programmatically building a BaseConfig with Type left as its zero value and calling Validate().
Common situations: Copy-paste of a scenario block that loses the executor line; assuming duration+vus alone imply constant-vus (they do not in the scenarios API); typos like 'executor' vs 'execution' are instead rejected at JSON decode with a different error.
Related errors
- scenario name can't be empty
- the scenario name should contain only numbers, latin letters
- exec value cannot be empty
- the startTime can't be negative
- the gracefulStop timeout can't be negative
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/92815be59d4ddc96.
Report an issue: GitHub.