grafana/k6 · error

110

110

Error message

test run was marked as failed

What it means

The k6/execution module lets a running script mark the whole test as failed via execution.test.markFailed() while still letting execution complete. After the run finishes, run() checks TestStatus.Failed() (set by the scheduler as ExecutionStatusMarkedAsFailed) and returns this error with exit code 110 (MarkedAsFailed), so CI detects script-level failure even though iterations completed.

Source

Thrown at internal/cmd/run.go:489

	// Check what the execScheduler.Run() error is.
	if err != nil {
		err = common.UnwrapSobekInterruptedError(err)
		logger.WithError(err).Debug("Test finished with an error")
		return err
	}

	// Warn if no iterations could be completed.
	if executionState.GetFullIterationCount() == 0 {
		logger.Warn("No script iterations fully finished, consider making the test duration longer")
	}

	// The execution module enables users to mark a test as failed, while letting the test
	// execution complete. As such, we check the test status here, after the test run has finished, and
	// ensure we return an error indicating that the test run was marked as failed, and the proper
	// exit code is used.
	if testRunState.TestStatus.Failed() {
		return errext.WithExitCodeIfNone(
			fmt.Errorf("test run was marked as failed"),
			exitcodes.MarkedAsFailed,
		)
	}

	logger.Debug("Test finished cleanly")

	return nil
}

func getSummaryMode(runtimeOptions lib.RuntimeOptions) (summary.Mode, bool, error) {
	sm, err := summary.ValidateMode(runtimeOptions.SummaryMode.String)
	if err != nil {
		return summary.ModeDisabled, false, err
	}

	return sm, sm != summary.ModeDisabled, nil
}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Search the script and all imported JS modules for 'markFailed' to find the failing call site
  2. Re-run with logging around the failing check to see the actual response or validation that triggered it
  3. If the failure condition is expected during exploration, remove or gate the markFailed call behind an env var
  4. Map exit code 110 to a distinct CI status so script-asserted failures are separated from thresholds (99) and config errors (104)

Example fix

// before
import exec from 'k6/execution';
check(res, { 'status 200': (r) => r.status === 200 }) || exec.test.markFailed();
// after
import exec from 'k6/execution';
check(res, { 'status 200': (r) => r.status === 200 });
if (res.status >= 500) exec.test.markFailed(); // only real server errors fail the run
Defensive patterns

Strategy: validation

Validate before calling

# Fail fast if the script can mark the run failed and you didn't expect it
grep -rn "markFailed" tests/ || echo "no markFailed calls"
# In-script, gate strictness behind a variable
// const strict = __ENV.STRICT === 'true';
// if (strict && res.status >= 500) exec.test.markFailed();

Prevention

When it happens

Trigger: A script (or imported helper library) calls exec.test.markFailed(), typically inside a check/assertion helper: import exec from 'k6/execution'; if (res.status !== 200) exec.test.markFailed(). The status propagates through the execution scheduler and is checked at the end of the run.

Common situations: Assertion wrappers around HTTP responses that mark the run failed on failed checks; guard code marking failure on error-rate spikes; teams surprised that a 'completed' run still exits non-zero.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/6464a16f36f79e82. Report an issue: GitHub.