In k6, what happens if a key in the exported `options` object is misspelled?
answer
- it warns, it does not stop
- strict pass, then a lenient retry
- unknown fields warning, run continues
- wrong type is 104, wrong name is not
basics
~20 sk6 logs one warning - There were unknown fields in the options exported in the script - and runs anyway with the default for the setting you meant. A misspelled root key never stops the run, so the run silently ignores it.
solid answer
~40 sk6 serialises the exported `options` value to JSON and decodes it strictly. If that strict pass finds a key it does not recognise at the root, k6 retries the decode leniently; the retry succeeds, k6 logs one warning - *There were unknown fields in the options exported in the script* - and the run continues with the default for whatever you meant to set. So `treshholds: {...}` does not fail the run, it produces a run with no thresholds. A value of the wrong *type* is different: that fails both passes and k6 exits **104**, invalid configuration. The asymmetry matters in CI, where a warning scrolls past and a green run looks like a passing one.
code
javascript · 10 linesexport const options = {
vus: 5,
duration: '30s',
// misspelled: k6 warns once and runs with no thresholds at all
treshholds: {
http_req_duration: ['p(95)<500'],
},
};
export default function () {}go deeper
Remember the direction of the failure: a misspelled option warns and the run continues. If a setting seems to have no effect, check the spelling of the key before suspecting k6.
Explain the strict decode followed by a lenient retry, and why that produces a warning rather than an error. Contrast it with a wrong-typed value, which fails both passes and exits 104.
Show how you stop this reaching production: fail the pipeline on the unknown-fields warning, check that the summary actually reports thresholds, and know that keys like features parse cleanly yet do nothing.
The tradeoff is tolerance versus trust. k6 chose to run rather than refuse, which means your team, not the tool, owns the guarantee that a green run measured what the script claims it measured.
## Two passes, and only one of them is strict k6 reads the exported `options` object by serialising it to JSON and decoding that JSON into its own internal configuration structure. The decode happens twice, and the difference between the two attempts is the whole answer: 1. The **first pass is strict** - unknown fields are rejected. If every key is recognised, k6 uses the result and moves on. 2. If the strict pass fails, k6 **retries leniently**, ignoring anything it does not recognise. 3. If the lenient retry succeeds, k6 logs a single warning - *There were unknown fields in the options exported in the script* - with the offending key named in the log entry's error detail, and **the run proceeds**. 4. If even the lenient retry fails, k6 treats it as bad configuration and exits **104**. A misspelled root key lands in step 3. `treshholds`, `vu`, `discardResponseBody` - all of them parse leniently, all of them warn, and all of them leave the setting you meant at its default. ## What each mistake actually produces | What you wrote | What k6 does | Run outcome | |---|---|---| | `treshholds: { ... }` | one warning, key ignored | runs with **no** thresholds | | `vus: 'ten'` | type mismatch, both passes fail | exits **104**, invalid config | | `stages: { duration: '1m' }` | array expected, object given | exits **104**, invalid config | | `features: ['x']` | key is known but not honoured here | warns, flag not enabled | | `ext: { loadimpact: { ... } }` | `ext` is a known root key | no warning at all, block ignored | The last two rows are the ones that catch experienced people. A key can be perfectly spelled, decode without complaint, and still do nothing. ## The one place it is fatal instead The leniency is a property of the **root** of the object. It does not extend downward: the decoder for the `scenarios` key is itself strict and has no lenient fallback, so an unrecognised key *inside* a scenario entry - one of that executor's settings, misspelled - makes the whole configuration parse fail and k6 exits **104** before a single request is sent. That is genuinely useful to know, because it means the two most common typos in a k6 script fail in opposite directions: - a typo at the root of `options` **warns and runs**, producing a green run that measured the wrong thing; - a typo inside a `scenarios` entry **stops the run immediately**, which is loud and easy to fix. Do not state the rule as "an unknown option means exit 104" - that is only half true, and it is the half that will not bite you. ## Keys that parse but do nothing Two cases are worth committing to memory in k6 v2: - **`features`** is a real root key, so it decodes without a warning about unknown fields, but feature flags cannot be set from the script's options. k6 logs *Feature flags in script options are not supported; use --features, K6_FEATURES, or the JSON config* and ignores the value. - **`ext`** is also a real root key. The `ext.loadimpact` block that older k6 material shows was removed in k6 v2.0.0 in favour of the root `cloud` key, but because `ext` itself still parses, a stale `ext.loadimpact` block produces no warning whatsoever. It is configuration that vanishes without a trace. ## How to stop losing settings this way - **Fail your pipeline on the warning.** The message is a single, stable string; grepping k6's output for `unknown fields` in CI turns a silent misconfiguration into a red build. - **Read the summary, not just the exit code.** A run whose thresholds were dropped by a typo reports no threshold results at all - an empty pass-rule section is the symptom. - **Verify the effective configuration.** `exec.test.options` exposes the consolidated configuration to the running script, so a script can log what it was actually given rather than what you believe you wrote. - **Keep the object small and reviewed.** Every key you add is a key that can be misspelled into silence; a short `options` object is easier to eyeball in a diff than a long one. The underlying design choice is defensible - k6 would rather run your test than refuse it over a stray key - but it puts the burden of noticing on you. Treat the warning as an error and the asymmetry stops mattering.
- Why does an unknown key inside a k6 `scenarios` entry behave differently from one at the root?The root decode has a lenient second attempt; the decoder for `scenarios` does not. It rejects unrecognised fields with no fallback, so the failure propagates out of the whole configuration parse and k6 exits 104 before the run starts. Same strictness setting, different recovery path.
- How would you tell from k6's output that a threshold key was misspelled rather than passing?A misspelled `thresholds` key means k6 registered no thresholds, so the end-of-test summary shows no threshold results and the run exits 0 regardless of latency. A real pass shows the rule and its measured value. The absence of the section, not a failure in it, is the tell.
saying these in an interview costs you the question
- Says any unrecognised option makes k6 exit 104
- Assumes a typo in options would fail the run loudly
- Thinks the unknown-fields warning names no key
- Believes a features key in options enables a feature flag
- Treats a green k6 exit code as proof thresholds ran