npm / mockserver-client
mockserver-client
What changed in mockserver-client 9, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-19.
75 breaking5 security2 deprecations38 new APIs and options6 performance24 behavior and defaults1 tooling32 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initmockserver-client 9183 changes
Breaking changes 75
Forwarded and proxied requests now carry the client's Accept-Encoding filtered to supported decompression formats; the Java client no longer adds gzip,deflate by default.
Bodies without Content-Type that are not valid UTF-8 are now preserved as exact binary bytes; callbacks, templates, WASM, logs, and HAR expose them as base64.
A message is now everything read in one pass, up to 256 KiB, rather than one network read. Back-to-back data may therefore match as one message, and forwarded messages can be larger.
Binary expectation response delays are now applied in order without holding a thread; empty response data means no reply.
Binary proxying now applies backpressure instead of buffering unlimited replies when clients do not read; writes stall without dropping data.
The binary proxy listener is called as soon as each message is read, on its own thread; its response is the first upstream bytes after that message or null.
The Java client's callback and breakpoint WebSockets now use the same trust and client-certificate settings as its HTTP requests.
Clearing with a DNS or binary matcher now clears only matching expectations; an empty request matcher clears all expectations and, for log/all types, matched DNS and binary log entries too.
The Java client trusts only the configured CA chain for MockServer's certificate; include MockServer's CA if it signs the server certificate.
With control-plane mTLS, Java clients trust only this chain for MockServer's certificate, and MockServer accepts only client certificates signed by this chain.
Rust struct literals for Delay now need to set newly added fields, or callers can use the provided constructors or builders.
Five distroless image variants move from Java 17 to Java 25, while -clustered moves to Java 21.
MockServer now refuses to start when DNS mocking is enabled but its DNS port cannot be used.
The setting and its Java methods are removed; configured values are ignored, and per-message forwarding cannot be restored.
Undecodable upstream responses now produce a 502 naming the cause and close the bad connection instead of relaying partial data or reusing it.
The Go client moves to the /v9 module path; update go get commands and imports from the /v7 or unsuffixed paths.
The Go client module moves to the /v9 path; update go get commands and imports to use it.
HTTP/2 and HTTP/3 HEAD responses no longer carry a body, including forwarded responses; tunnelled responses preserve the headers a direct connection sends.
HTTP/3 startup now refuses a UDP port already held by another application on macOS.
Setting the HTTP/3 port without the required native, or when the UDP port cannot be used, now prevents startup instead of silently degrading.
Rust struct literals for HttpTemplate now need to set newly added fields, or callers can use the provided constructors or builders.
Idle client connections now close after five minutes by default; set the timeout to 0 to restore the previous behavior.
When expectations in an initialization file repeat an id, the last one is kept in the first occurrence's position, matching PUT /mockserver/expectation behavior.
The container heap cap drops from 75% to 45% of the memory limit. A 256 MiB limit is no longer supported unless a small explicit heap is set.
DNS and HTTP/3 ports now bind to localBoundIP as well; clients must send those requests to that address when it is set.
Binary expectations now match messages on proxied binary connections by default; set the option to false to always forward, as in 8.0.0.
The setting now limits HTTP/2 and HTTP/3 request headers and upstream response headers as well as HTTP/1.1 headers. Its default is 256 KB; set it to 8192 to retain the old HTTP/2 and HTTP/3 limit.
The default changed from unlimited to 256 KB, applying uniformly across protocols.
This setting caps per-expectation mismatch log entries per request, defaulting to 50; set it to -1 to log every comparison. Matching and closest-match results are unchanged.
Oversized request bodies now receive 413 instead of a reset; HTTP/3 compressed bodies are limited by decompressed size.
The metric now has a reason label with values ring_full and in_flight_bytes; scripts and PromQL queries that assumed an unlabelled metric may need adjustment.
The metric now counts evicted entries rather than eviction episodes, so values are much larger and alerts need retuning.
The Node client now has an exports map that permits named package paths and blocks unlisted deep paths with ERR_PACKAGE_PATH_NOT_EXPORTED.
The package now has an exports map, so imports of unlisted internal paths fail to resolve.
The deep-import TypeScript typings no longer declare a default export; import from mockserver-client itself, use a namespace or require import, or enable esModuleInterop.
Its TypeScript typings now describe a plain object of named exports rather than a default export; the .default property is no longer typed.
The package now publishes its TypeScript typings, which use Node's types and therefore require @types/node.
A Node callback is no longer re-registered with its full times limit after MockServer removes its expectation; reconnects occur only while the expectation remains.
The launcher runs the bundled Java runtime directly without a shell and passes arguments separately; MOCKSERVER_JAVA_OPTS is split on whitespace with quoted text kept together, and spawnOptions.shell is ignored.
The Node browser transport now rejects 4xx and 5xx responses as the Node transport does.
withStyle and withSchemaType now return a new instance instead of mutating the existing instance; callers must use the returned value to observe the change.
withStyle and withSchemaType now return a new instance instead of mutating the existing instance; callers must use the returned value to observe the change.
Verification now counts only requests for the matched OpenAPI operation; verifySequence behavior is unchanged.
Now rejects instead of hanging when MockServer answers with an error.
withStyle now returns a new instance instead of mutating the existing instance; callers must use the returned value to observe the change.
The PHP launcher builds a quoted cmd.exe command line on Windows and throws BinaryInstallException for unsafe arguments or more than one percent sign across the path and arguments.
The MCP server now rejects calls missing required arguments with JSON-RPC error -32602 and names the missing arguments in data.missingArguments; null counts as missing.
Unknown fields now produce a 400 instead of silently checking at least one message; count constraints belong inside count.
On Windows, the launcher invokes cmd.exe with quoted arguments and raises ValueError for unsafe characters or more than one percent sign across the path and extra arguments.
Bodies whose bytes are already materialized are replayed verbatim instead of being decoded with replacement characters and re-encoded when the declared charset does not match the bytes.
Response verification now applies body matchers in verify and verifySequence instead of silently replacing them with an empty-object match.
A client that stops reading a response is now disconnected or reset after one minute by default; set this to 0 to disable the timeout.
The Python client now returns a DnsRequestDefinition or dict for DNS requests instead of an empty HttpRequest.
The Python client now returns a DnsRequestDefinition or dict for DNS requests instead of an empty HttpRequest.
The Java client now throws for control-plane errors instead of returning the error's text.
The Java client now raises for status codes of 400 or greater instead of returning the error text as its result.
An unfiltered listing includes expectations whose request matcher is not(...); DNS/binary filters return only matching expectations.
The Java client now throws for control-plane errors instead of returning the error's text.
The Java client now raises for status codes of 400 or greater instead of returning the error text as its result.
The Node client's TypeScript return type changes to Promise<RequestDefinition[]>; narrow each result to HttpRequest before reading HTTP-specific fields.
The Node client's return type is now Promise<RequestDefinition[]> rather than Promise<HttpResponse[]>; narrow results before using HTTP-specific fields.
The Node client's TypeScript return type changes to Promise<RequestDefinition[]>; narrow each result to HttpRequest before reading HTTP-specific fields.
The Node client's return type is now Promise<RequestDefinition[]> rather than Promise<HttpResponse[]>; narrow results before using HTTP-specific fields.
Enums are now non-exhaustive and server-sent unknown values map to Unknown; Unknown cannot be serialized back to the server.
Public enums are now non-exhaustive, requiring wildcard match arms; server-sent enums gain an Unknown variant that cannot be sent back.
Mutating the set returned by this method is no longer observed; change Subject Alternative Name lists through Configuration methods.
Mutating the set returned by this method is no longer observed; change Subject Alternative Name lists through Configuration methods.
Start failures now reject with an Error when Java cannot run or exits before readiness; failed starts clean up the launched process, and polling has a timeout.
Response status codes outside 100–999 are now rejected; invalid entries in initialization or persisted expectations are skipped with a warning.
Stop failures and timeouts now reject and stop the launched process; refusal or server errors no longer resolve as if MockServer stopped.
TCP chaos latency and bandwidth now behave like a slow link: inbound data stays ordered, bandwidth is shared per connection, and latency plus bandwidth settings add together.
The option is now on by default, so a failing or invalid response or forward template returns 500 rather than 404 or 502.
A verification with an upper bound now fails rather than passing when the event log is truncated.
Verification sequences now check DNS/binary steps and match requests as received when redaction is enabled; verification kinds that cannot count DNS/binary traffic are rejected with 400.
No longer passes when the server rejected the call or could not be reached.
Security 5
The Ruby launcher builds a quoted cmd.exe command line on Windows and raises MockServer::Error for unsafe arguments; it no longer uses a shell on Linux or macOS.
The launcher builds a quoted cmd.exe command line on Windows and refuses launcher paths containing a double quote, line break, NUL, or more than one percent sign.
The launcher builds a quoted cmd.exe command line on Windows and refuses launcher paths containing a double quote, line break, NUL, or more than one percent sign.
The launcher builds a quoted cmd.exe command line on Windows and refuses launcher paths containing a double quote, line break, NUL, or more than one percent sign.
Internal x-http2 headers are no longer leaked into recorded, matched, or forwarded requests and responses.
Deprecations 2
http_request remains supported as a deprecated alias of request_override.
http_response remains supported as a deprecated alias of response_override.
New APIs and options 38
Helm adds a pre-stop sleep setting, defaulting to 0 and requiring Kubernetes 1.30 or newer.
Helm adds a termination grace period setting, defaulting to 45 seconds, for graceful draining.
Binary responses can select whether to answer only, answer and forward while dropping the server reply, or forward and replace the server reply.
Bounds how long a callback waits for its client id; callback and breakpoint registration rejects if the id does not arrive within the configured timeout.
Go, .NET and Rust add a typed
CHECK_FAILURE_RATEthreshold metric for load scenarios.Closes callback and breakpoint WebSockets without resetting MockServer.
The selected DNS port can be read from
ClientAndServer, including the instance injected by the JUnit 5 extension.Python and Ruby clients gained a conditional-matcher type.
Go adds conditional request matcher fields and a
ConditionalRequest(...)helper.Python can build and read conditional if/then/else request matchers using
if_request,then_request,else_requestandnot_condition.Typed client calls compare a described request with every active expectation, field by field.
Typed client calls explain which expectation would serve a recorded request, why earlier expectations were passed over, which lower-priority expectations it hides, and how the request was handled.
Typed client calls list the closest expectations for recent unmatched requests, optionally with a suggested JSON patch for each.
Forward loops back to MockServer stop after 10 hops with 508 Loop Detected; setting the limit to 0 disables the forwarding header.
The dashboard uses this authenticated, redacted endpoint to load full bodies for entries whose displayed bodies are truncated.
Rust and PHP add a helper for building conditional request matchers.
.NET adds
If,ThenandElsefields and theRequestIf(...)helper for conditional request matchers.The Java client sends and exposes the primary flag, allowing a primary response action to be combined with a second action.
Configures the maximum input length for deterministicFromInput embedding mocks, which now default to a 1,048,576-character limit.
Python, Go, .NET, Rust and PHP load-scenario steps can specify per-step checks and a
checkslist.Rust load steps gain
name(...)andlabel(key, value)methods, and load scenarios gainlabel(key, value).The Rust client's LoadThresholdMetric enum gains the CheckFailureRate variant.
The enum gains a CheckFailureRate variant for the new per-step load check threshold.
The event log is now bounded by size as well as count. The setting is enabled by default, using a heap-based limit; set it to 0 to restore count-only bounding.
Delayed responses are capped to bound resource use; requests within the limit are unaffected.
Queued template actions are capped to bound resource use; requests within the limit are unaffected.
A new metric is provided for pending delayed tasks.
A new metric counts response write stalls, labelled by protocol and scope.
A new metric counts WebSocket read pauses.
Builder types now live in this module, which can be augmented instead of mockserver-client/llm.
Set this property to false to opt out of the dev-mode defaults used by the JUnit rule and extension.
The Spring listener exposes the selected DNS port through the
${mockServerDnsPort}placeholder.The new
@MockServerDnsPortannotation exposes the selected DNS port.The selected DNS port can be read from
MockServerRule.@MockServerTestnow acceptsmockserver.dnsEnabledandmockserver.dnsPort.Python and Ruby clients now support per-step load checks.
The Java client adds a method to retrieve recorded request definitions, including DNS queries and binary messages.
TurnBuilder is now declared alongside the other builder constructors.
Performance 6
The event-log thread now batches wake-ups while traffic flows, reducing CPU use; log entries may reach the console, disk capture, and dashboard up to 10 ms later.
The receive buffer is sized up to reduce stalls with curl's OpenSSL QUIC stack; raise the host's net.core.rmem_max for the full 4 MiB buffer.
The GraalVM engine is shared process-wide and parsed scripts are cached; template rendering uses a dedicated bounded pool so saturated renders do not block unrelated event-loop work.
Shutdown is effectively instant after removing a redundant fixed Netty quiet-period wait.
Disk capture is cheaper and batches writes. Output lines may differ byte-for-byte while parsing to the same JSON; a hard kill can lose up to 8 KB of recent lines.
Three forwarding and proxy-pass paths no longer block a pool thread for the full upstream round trip, increasing proxy concurrency with a small thread pool.
Behavior and default changes 24
Binary proxying now keeps one upstream connection for the client's whole connection, relays TLS on that connection, and tunnels through configured upstream proxies.
Closest-match comparisons now stop after the first 1,000 expectations in serving order; the hint indicates when it was truncated.
Unexpected internal failures now return a 500 with a generic message and correlation id; invalid requests remain 400 responses.
HTTP/2 tunnels now answer 100 Continue themselves and pass the request and full body once; unsupported expectations receive 417 and oversized bodies receive 413.
Forwarded-request metrics now label at most 500 distinct upstream hosts; additional hosts are grouped under _other.
HTTPS and SOCKS upstream proxies now resolve destination host names themselves instead of requiring MockServer to resolve them.
Invalid forwarding keys or certificates and undecodable upstream responses do not trigger retries; idempotent requests are retried once on a fresh connection after a pooled connection closes on reuse.
Uploads abandoned by the client are logged once at INFO rather than ERROR with a stack trace; nothing is logged at WARN or ERROR.
An HTTP/2 upstream connection may now open only one stream of its own at a time, with the same per-stream body-piece limit.
Docker images now use ZGC by default; -aot retains G1. Overriding JAVA_TOOL_OPTIONS replaces the default options, so include -XX:+UseZGC to retain ZGC.
The JUnit 5 extension now defaults to dev mode, using maxLogEntries=1000 and maxExpectations=1000 instead of heap-derived sizes; set mockserver.devMode=false or raise the caps if deeper history is needed.
The JUnit 4 rule now defaults to dev mode, using maxLogEntries=1000 and maxExpectations=1000 instead of heap-derived sizes; set mockserver.devMode=false or raise the caps if deeper history is needed.
Log entries now include each request or response body once; message, arguments, and proxied-exchange expectation bodies use short forms instead of repeating full bodies.
Peer-closed or reset connections are logged at cause-appropriate levels in MockServer's own log; set DEBUG to see the quieter entries.
The default cap rises from 100,000 to 250,000 on large heaps; the effective default also scales with the reduced container heap cap.
The default is now 50 instead of -1, limiting logged expectation mismatch entries per request without changing matching or verification behavior.
A new metric counts drift analyses skipped when the backlog fills, rather than allowing the backlog to grow without limit.
CommonJS-style imports work with or without esModuleInterop; default imports require esModuleInterop.
When MockServer runs as its own process, Netty off-heap buffer memory is capped by default at a quarter of max heap, with a 64 MiB minimum and a cap no greater than heap; reaching the cap closes the connection that…
With transparentProxyEnabled, PROXY-prefixed connections are parsed and matched or recorded as HTTP, and remote-address callbacks and templates see the real client address.
Calls filtered by request now also return error log entries associated with that request.
Calls filtered by request now also return error log entries associated with that request.
Inbound and outbound TLS handshakes now use this timeout, with a 20-second default, instead of a hard-coded 10-second limit.
Verifying by the id of a DNS or binary expectation now counts the DNS queries or binary messages that expectation answered.
Tooling 1
The Node client typings now declare this existing runtime method, with a typed Har document as its resolved value.
Fixes and other changes 32
.NET and Rust clients can now read a load scenario using the CHECK_FAILURE_RATE threshold.
Tunnel handling now preserves streamed responses, isolates request and stream failures, routes known destinations through MockServer matching, and avoids losing or duplicating requests in the described edge cases.
HTTP/3 request bodies with content encodings are decompressed for matching and forwarding, while original compressed bytes are retained.
verify, verifyNever, and sequence verification now count DNS and binary requests matched by request or expectation id.
Python, Ruby, Rust, Go, .NET and PHP clients now support building and reading back previously missing expectation fields, including overrides, matchers, response settings, templates and action settings.
Expectation.from_dict no longer drops an OpenAPI request matcher.
HTTPS forward-proxying now pools HTTP/2 upstream connections, reducing local-port exhaustion under sustained load.
HTTP/2 gRPC streams, including server reflection, now end normally when the client ends its request with trailers instead of closing the connection and other streams.
After-raw-response pipelined exchanges now preserve the next response on the same connection.
Mocked 1xx-only responses, or 1xx responses with a body or trailers, are sent as interim responses followed by a clean stream reset instead of hanging clients or breaking connections.
Unexpected upstream connection errors now fail pending forwards, send GOAWAY, close the connection, and prevent its reuse from the pool.
HTTP/3 bodies without Content-Encoding retain the bytes received when forwarded; text without a charset still uses ISO-8859-1, while JSON and XML default to UTF-8.
The HTTP/3 UDP port is released when the server stops or fails to start, allowing immediate restart or another application to bind it.
Python's HttpOverrideForwardedRequest now supports request_override and response_override, sends overrides under accepted names alongside modifiers or response_template, and reads overrides back from MockServer.
Reading back a Java API header or query parameter added with an empty or null value list no longer throws NullPointerException.
Header sections exactly at the configured limit are accepted regardless of how network reads split the final header line.
The minimum is now 1 byte; zero or negative values no longer produce inconsistent body limits across protocols.
The minimum is now 1 byte; zero or negative values no longer produce inconsistent body limits across protocols.
A Java client callback whose WebSocket registration fails no longer occupies a WebSocket expectation slot.
Named imports now work; previously only the default import worked.
Named ES-module imports in the Node client and launcher were fixed.
The bypass list now applies consistently to HTTP, HTTPS, and SOCKS upstream proxies; leading-dot suffixes and normalized IPv6 addresses are supported.
The PHP client now sends an empty request matcher as an object rather than an array.
Free-port helpers no longer return a port another application is listening on at 127.0.0.1 or ::1.
The Python synchronous client now exposes respond_with_grpc_bidi, previously available only on its async sibling.
Proxied response headers, trailers, and cookies beginning with matcher marker characters are recorded literally rather than parsed as matcher syntax.
Retrieving log messages without a request matcher now includes messages about DNS and binary requests.
Rust clients can now parse load scenarios that omit abortOnFail, thresholds, stages, rows or captures, which previously failed to parse.
The Node launcher now honors the configured startupRetries value instead of always reading it as 500.
Verification.from_dict no longer drops an OpenAPI request matcher.
The Python synchronous client now exposes with_chaos, previously available only on its async sibling.
The Python synchronous client now exposes with_steps, previously available only on its async sibling.