k6 v2.4.0 is here 🎉! This release includes:
- Experimental tracing of test runs, scenarios, VUs, and iterations.
- Ed25519 signatures and X25519 key agreement in WebCrypto.
- Credential-header redaction for HTTP and gRPC debug logs.
- Structured gRPC error details.
- Fixes for browser selectors, JavaScript memory leaks, and asynchronous error reporting.
- Deprecation of the built-in InfluxDB and Prometheus remote-write outputs ahead of k6 v3.
Upgrade notes
Recheck browser received-data thresholds #6496
browser_data_received now uses the encoded transfer size reported by Chrome DevTools when a response finishes, including responses in a redirect chain. This can differ from the previously computed response size, particularly for compressed responses. Recheck thresholds and baselines that use this metric when upgrading from an earlier version.
Conversion changes for extension authors #6629
Extension authors should check code that relies on Sobek's Go-to-JavaScript value conversion. Nil slices now become null/undefined instead of empty arrays, and Runtime.ToValue() dereferences only one pointer level. Use a non-nil empty slice when an extension API should return an empty JavaScript array. This guidance concerns extension implementations; k6 preserves empty-array results for the affected built-in browser, HTML, and gRPC APIs.
Deprecations
InfluxDB and Prometheus remote-write outputs #6665
The built-in influxdb and experimental-prometheus-rw metrics outputs are deprecated and planned for removal in k6 v3. They continue to work in v2.4.0 but now log a deprecation warning when used. We recommend migrating to the opentelemetry metrics output.
New features
Trace the test execution hierarchy #6605
The experimental native-tracing feature adds spans for the test run, each scenario, each VU activation, and each iteration. Browser spans become children of the corresponding iteration, so you can follow browser activity within the wider test execution.
Enable the feature and configure an OpenTelemetry traces output:
k6 run --features=native-tracing --traces-output=otel=http://localhost:4318 script.jsThe hierarchy is k6.run → scenario → vu → iteration. Spans include scenario and execution identifiers. Failed iterations record errors, while iterations interrupted by the end of a scenario are marked as interrupted. The feature is opt-in and requires an enabled traces output.
Sign and exchange keys with Ed25519 and X25519 #6525
WebCrypto now supports Ed25519 signing and verification, and X25519 key agreement. Both algorithms support key generation and import/export, including JWK keys.
For example, generate an Ed25519 key pair, sign a message, and verify its signature:
export default async function () {
const keys = await crypto.subtle.generateKey('Ed25519', true, ['sign', 'verify']);
const message = new Uint8Array([104, 101, 108, 108, 111]);
const signature = await crypto.subtle.sign('Ed25519', keys.privateKey, message);
const valid = await crypto.subtle.verify('Ed25519', keys.publicKey, signature, message);
console.log(valid); // true
}Thanks, @BlairCurrey!
Hide credential headers in debug logs #6607
Use --http-debug-redact with --http-debug to mask credential headers in HTTP requests and responses, and in gRPC metadata:
k6 run --http-debug --http-debug-redact script.jsRedaction covers Authorization, Proxy-Authorization, Cookie, Set-Cookie, X-API-Key, X-Auth-Token, and X-Amz-Security-Token. Authentication schemes, cookie names, and cookie attributes remain visible to help with debugging. You can also enable it through K6_HTTP_DEBUG_REDACT or the httpDebugRedact script option.
Redaction is disabled by default. It only masks these headers and metadata keys; URL query parameters and bodies logged with --http-debug=full remain unchanged. Thanks, @digitalcrab!
Inspect structured gRPC error details #5711
gRPC responses now expose structured error details from grpc-status-details-bin through response.error.details. This lets scripts inspect field-validation errors, retry information, and other details supplied by a server instead of relying only on an error message.
k6 resolves both standard Google error-detail types and custom types loaded through the client. If details cannot be converted, the error still includes its code and message. See the gRPC error-details example for a complete script. Thanks, @yordis!
Send HTTP QUERY requests #6481
The new http.query(url, body, params) convenience method sends an HTTP QUERY request. It accepts a request body and the same request parameters as the other HTTP convenience methods.
import http from 'k6/http';
export default function () {
http.query('https://example.com/search', JSON.stringify({ term: 'k6' }), {
headers: { 'Content-Type': 'application/json' },
});
}Thanks, @ashrafiucse!
UX improvements and enhancements
- #6528 Adds
K6_PROMETHEUS_RW_SIGV4_TOKENfor AWS session credentials when signing Prometheus remote-write requests. Use it together with the existing region, access-key, and secret-key options. Thanks, @ashrafiucse! - #6483 Supports fetching intermediate TLS certificates supplied as PKCS#7/CMS bundles, including PEM-armored bundles, when
tlsAIAFetchis enabled. This allows certificate-chain completion with more certificate authorities. Thanks, @ashrafiucse! - #6565 Accepts the standard
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256andTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256cipher-suite names while preserving the existing aliases. Thanks, @HakeemTheEmperor! - #6561 Includes the searched path in errors for missing local files. Thanks, @kriyanshii!
- #6581 Adds the missing script argument to two
k6 runhelp examples. Thanks, @ZainnQureshii! - #6403 Adds a proxy option to the Prometheus remote write output. Thanks, @KR-Ravindra!
Bug fixes
- #6637 Makes
browserContext.pages()return pages in attachment order instead of an unpredictable order, preserving the order of remaining pages when a page closes. Thanks, @adityareddy-dev! - #6629 Fixes a JavaScript memory leak introduced in v2.2.0: WeakMap entries whose values reference their keys can now be collected again. This affects scripts using, for example, the jslib URL polyfill.
- #6614 Reports an error when a script function returns a promise that remains pending after the event loop has no work left to settle it. Normal interruption at the end of a scenario or test does not produce this error. Thanks, @muhammadmobi!
- #6406 Reports unhandled promise rejections as script exceptions, with the corresponding script-error abort reason and an
unhandled script exceptionlog hint. Thanks, @IslamElsayed! - #6587 Prevents panics when formatting unhandled promise rejections whose stack access, string conversion, or export executes JavaScript.
- #6578 Fixes browser
text=and bare quoted selectors,visible=falsematching, and selector chaining after a visibility filter. Also fixes stalehasText/hasNotTextresults after DOM updates, escaping of text and regular-expression values, accessible names containing CRLF, and chained selectors across nested open shadow roots, includingnth()andall(). - #6496 Uses the encoded transfer size reported by Chrome for
browser_data_received, including redirects. Values can differ from earlier releases, particularly for compressed responses, so existing thresholds and comparisons might need adjustment. Thanks, @Saad259! - #6390 Makes request objects reflect URL, method, header, and body overrides from
route.continue()before request events are emitted. - #6167 Prevents empty duplicate browser navigation spans on client-side redirects, while preserving tracing for navigation after a download or a response that does not commit a document.
- #6568 Prevents screenshot-upload errors from exposing credentials or internal storage URLs, and avoids echoing secret values in screenshot-output configuration errors.
- #6567 Preserves
=characters insideK6_BROWSER_SCREENSHOTS_OUTPUTconfiguration values. - #6591 Reports browser initialization configuration errors without panicking.
- #6381 Returns a regular 401 response with an empty body when digest authentication finds no usable challenge, instead of reporting a closed-response-body error. Replaces the unmaintained digest-authentication library. Thanks, @ashrafiucse!
- #6486 Prevents digest authentication from removing credentials from a shared
http.urlvalue used by subsequent requests. Thanks, @ashrafiucse! - #6575 Fixes a race between HTTP transport initialization and WebSocket or gRPC use of the same VU's TLS configuration.
- #6590 Treats HTML
checkedanddisabledattributes as boolean attributes during form serialization, so their presence determines their effect regardless of their value. Thanks, @sebxt! - #6489 Supports ECDH
deriveBitslengths that are not multiples of eight and clears unused trailing bits. Thanks, @hyuraku! - #6379 Rejects creating a
k6/websocketsconnection in the init context with an error. Thanks, @ousamabenyounes! - #6610 Reports gzip finalization errors in compressed CSV and JSON output, as well as buffered-write errors when closing compressed JSON output. Thanks, @skdas20!
- #6497 Marks the ramping-arrival-rate progress bar as complete when the executor finishes early. Thanks, @NitinKumar004!
Maintenance and internal improvements
- #6629, #6640 Update Sobek and JavaScript conformance expectations. Improvements include lazy string concatenation, regular-expression handling, typed-array operations, and parsing and BigInt fixes. Float16Array conformance tests are now enabled, and compiler error handling is adapted to Sobek's updated source-location API.
- #6551 Updates CDP to v0.158.3 and adapts the browser implementation to its typed command API, including changes to timestamps, binary payloads, and execution-context destruction handling.
- #6541, #6542 Apply the
golang.org/x/netv0.60.0 security update to k6 and the gRPC example server. - #6662 Updates k6's
golang.org/x/netdependency to v0.62.0 for security fixes in HTML parsing and rendering. - #6249 Adds gRPC proto-loading coverage with the client and server running in separate processes. Thanks, @djedi-knight!
- #6635 Fixes serving browser test fixtures on Windows. Thanks, @adityareddy-dev!
- #6534 Updates goroutine-leak checks for Go tip's Windows synchronous I/O worker. Thanks, @NitinKumar004!
- #6573 Makes cloud tar-archive tests less flaky.
- #6527 Uses the shared k6 CI configuration to select the Go version for browser end-to-end tests.
- #6477, #6356, #6501, #6499, #6508, #6500, #6377, #6419, #6514, #6512, #6405, #6546, #6510, #6378, #6509, #6520, #6549, #6550, #6560, #6513, #6582, #6584, #6521, #6597, #6595, #6596, #6302, #6564, #6517, #6263, #6537, #6359, #6645, #6652 Updates the Docker build image to Go 1.27.3 and the runtime image to Alpine 3.24.2, Brotli to v1.2.8, goquery to v1.13.0,
klauspost/compressto v1.20.3, k6provider to v0.5.1, protoreflect to v1.18.1,go-colorableto v0.1.16, Prometheus client-model to v0.6.3, andgolang.org/x/cryptoto v0.58.0. Also updates related Go dependencies, generated Protobuf packages, Docker image digests, GitHub Actions, and k6 CI tooling. Example updates include Grafana v13.2.4 and gRPC v1.84.0 for the example server.