Skip to content

k6 Scenario Executor Not Running Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about k6 scenario executor not running fix. We cover key concepts, practical examples, and best practices.

Your k6 scenario does not run — the output shows zero iterations for a defined scenario, or the startTime delay never begins. The executor type, VU count, or iteration count is misconfigured, causing the scenario to be skipped.

The Problem

import http from 'k6/http';

export const options = {
  scenarios: {
    smoke: {
      executor: 'constant-vus',
      vus: 5,
      duration: '10s',
      startTime: '10s',  // Start after 10 seconds
    },
    load: {
      executor: 'ramping-vus',
      stages: [
        { duration: '30s', target: 50 },
        { duration: '1m', target: 50 },
        { duration: '10s', target: 0 },
      ],
    },
  },
};

export default function () {
  http.get('https://api.example.com');
}
ERRO[0000] executor "load" — ramping-vus has no stages defined?

The output shows only the load scenario runs while smoke never executes. The test duration ends before smoke starts because startTime in smoke pushes it past the overall test run time.

Step-by-Step Fix

1. Ensure scenarios fit within total test time

export const options = {
  scenarios: {
    smoke: {
      executor: 'constant-vus',
      vus: 5,
      duration: '10s',
      startTime: '0s',  // Start immediately
    },
    load: {
      executor: 'ramping-vus',
      startTime: '15s',  // Start after smoke ends
      stages: [
        { duration: '30s', target: 50 },
        { duration: '1m', target: 50 },
        { duration: '10s', target: 0 },
      ],
      gracefulRampDown: '5s',
    },
  },
};

2. Use the per-vu-iterations executor

export const options = {
  scenarios: {
    functional: {
      executor: 'per-vu-iterations',
      vus: 10,
      iterations: 5,  // Each VU runs 5 iterations
      maxDuration: '30s',
    },
  },
};

3. Use the constant-arrival-rate executor

export const options = {
  scenarios: {
    throughput: {
      executor: 'constant-arrival-rate',
      rate: 100,
      timeUnit: '1s',     // 100 iterations per second
      duration: '1m',
      preAllocatedVUs: 10,
      maxVUs: 50,
    },
  },
};

4. Use the externally-controlled executor

export const options = {
  scenarios: {
    live: {
      executor: 'externally-controlled',
      vus: 10,
      maxVUs: 200,
      duration: '10m',
    },
  },
};

5. Combine multiple executor types

export const options = {
  scenarios: {
    warmup: {
      executor: 'constant-vus',
      vus: 5,
      duration: '30s',
      startTime: '0s',
      gracefulStop: '5s',
    },
    spike: {
      executor: 'ramping-arrival-rate',
      startTime: '35s',
      stages: [
        { duration: '10s', target: 500 },
        { duration: '30s', target: 500 },
        { duration: '10s', target: 0 },
      ],
      preAllocatedVUs: 20,
      maxVUs: 200,
    },
  },
};

Expected output:

     scenario: warmup ........... 150 iterations
     scenario: spike ............ 15000 iterations
     ✓ both scenarios completed successfully

Prevention Tips

  • Set startTime explicitly to sequence scenarios correctly
  • Use gracefulStop to prevent VU mid-iteration terminations
  • Ensure maxDuration or overall test time covers startTime + scenario duration
  • Use per-vu-iterations for functional testing and constant-arrival-rate for throughput testing
  • Preview scenario timing with k6 run --dry-run script.js

Common Mistakes with scenario executor

  1. Mixing let bindings with <- bindings in do notation, producing type errors
  2. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  3. Non-exhaustive pattern matches that compile with warnings then crash at runtime

These mistakes appear frequently in real-world K6 code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What executor type should I use?

Use constant-vus for steady load, ramping-vus for gradual load changes, per-vu-iterations for functional tests (each VU runs N iterations), constant-arrival-rate for target throughput, ramping-arrival-rate for changing throughput, and externally-controlled for live control via the k6 REST API.

Can scenarios share VUs?

No, each scenario has its own VU pool. The total VUs across all scenarios is the sum of each scenario's VU count/k8. Use the startTime option to stagger scenarios and prevent resource contention.

How do I stop a scenario mid-execution?

Set gracefulStop to allow ongoing iterations to complete. For immediate stop, use the gracefulRampDown: '0s' option. For externally-controlled executors, use the k6 REST API to change VU count to zero.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro