# REST Assured 6.2.0

> Release notes for REST Assured 6.2.0.

## Highlights

* The `rest-assured` module is now written entirely in Java and no longer depends on Groovy (`org.apache.groovy:groovy` and `groovy-xml`) directly. Groovy still comes transitively through `json-path` and `xml-path`, which use it for GPath, so the dependencies on your classpath are unchanged. The `rest-assured` and `rest-assured-common` OSGi bundles no longer import the Groovy packages, and `rest-assured-common` no longer depends on Groovy at all.

* Fixes for tests that run in parallel. Changing the static configuration (for example `RestAssured.filters(..)`, `replaceFiltersWith(..)`, `registerParser(..)` or `unregisterParser(..)`) while another thread calls `given()` could fail with a `ConcurrentModificationException` or lose filters. `given()` no longer changes any shared state, and the public static fields of `RestAssured`, `RestAssuredMockMvc` and `RestAssuredWebTestClient`, as well as `JsonPath.config`, `XmlPath.config` and `JsonSchemaValidator.settings`, are now `volatile`, so a value set before the tests start is seen by every thread. `HttpClientConfig.reuseHttpClientInstance()` no longer creates more than one `HttpClient` when several threads send their first request at the same time. The javadoc of `RestAssured`, `RestAssuredMockMvc` and `RestAssuredWebTestClient` now explains how to use the static configuration with parallel tests. In short:

  * Set the static defaults once, before the tests start running in parallel (for example in a `@BeforeAll` method), and don’t change them while requests are being made.
  * Put values that differ between tests in the request specification instead, for example `given().baseUri("http://localhost").port(8081)` or `given(spec)`.
  * Don’t execute the same request specification from several threads at once. Start a new one with `given()` in each thread.
  * Filters added with `RestAssured.filters(..)` are shared by all requests and must be thread safe.
  * The reused `HttpClient` from `reuseHttpClientInstance()` is reconfigured by every request, so it still must not be used by requests that run at the same time.

* `auth().certificate(certURL, password)` and `RestAssured.certificate(certURL, password)` now send the client certificate in the file to servers that ask for one (mutual TLS), as documented. Before, the file was only used as trust store. In the same way, a key store configured with `keyStore(..)` but without a trust store is now used, where it used to be ignored. Both are non-backward compatible, see [SSL and certificates](/release-notes/6-2/#ssl-and-certificates).

  ```java
  given().auth().certificate("/client-keystore.jks", "password").when().get("https://localhost:8443/secured").then().statusCode(200);
  ```

* JsonPath and JSON body assertions can read a key that contains a colon with the dot notation. This used to fail with “Invalid JSON expression”:

  ```java
  get("/status").then().body("message.ErrorCode:", equalTo(0));
  ```

  A colon in a ternary (`a ? b : c`) or Elvis (`a ?: b`) expression, in a closure or in a quoted string is left as is.

* Request logging no longer prints the content of a multipart `File` whose mime type isn’t text, such as `application/octet-stream` (the default) or `image/png`. Since 5.5.0 the whole file was dumped to the log. Such a part is now logged as the path of the file, as before 5.5.0. A file with a text mime type (`text/*`, JSON, XML or HTML) is still logged, and is now read with the charset of the part (or of its mime type), or UTF-8 if none is given.

* Clearer errors. Many failures that used to surface as Groovy exceptions (`groovy.lang.MissingMethodException`, `GroovyRuntimeException`, `GroovyCastException`), a `NullPointerException` or a `StackOverflowError` now either work or fail with an exception that says what is wrong. For example:

  * Sending a request directly from a specification built by `RequestSpecBuilder.build()` fails with an `IllegalStateException` that tells you to use `given().spec(spec)` or `given(spec)`.
  * Sending a request directly from a specification built by `ResponseSpecBuilder.build()` fails with an `IllegalStateException` that tells you how to add it to a request.
  * A failed body path assertion on a body that the path can’t navigate shows the response body instead of the literal text `$contentParser`.
  * Form authentication names the additional field that isn’t on the login page, and says when a redirect to the login page has no Location header.
  * A key store given as a `KeyStore` without a password, whose private key needs one, fails with a message that says how to set the password.
  * When SSL settings can’t be applied to an `http` request that is redirected to `https`, the `SSLException` ends with the message of the cause (for example a `FileNotFoundException` for a missing trust store) instead of “null”.

## Non-backward compatible changes

### Request bodies and content types

* A request body sent with `noContentType()` no longer gets a Content-Type header. Before, a binary body (`byte[]`, `InputStream` or `File`) got `Content-Type: */*`, and when an expected response content type was set (for example `expect().contentType(ContentType.JSON)`) that content type was sent as the request Content-Type. If the server needs a Content-Type, set it with `contentType(..)` instead of `noContentType()`:

  ```java
  given().contentType(ContentType.BINARY).body(bytes).when().post("/upload"); // instead of given().noContentType().body(bytes)
  ```

* A request body that isn’t a `String` (for example a `byte[]`, `InputStream` or `File`) sent with content-type `application/x-www-form-urlencoded` now fails with an `IllegalArgumentException` explaining that a form url-encoded body must be a `String`. Before, it failed with a `groovy.lang.MissingMethodException`. Send the body as a `String`, or use `formParam(..)`.

* A `groovy.lang.Writable` request body sent with a text content-type is now sent as its `toString()` instead of what its `writeTo(..)` method writes. Groovy’s own Writables (such as `JsonBuilder` and `GString`) produce the same output either way. A Groovy `WritableFile` (`file.asWritable()`) is now sent like any other `File`, read with the charset of the request content-type. If your own `Writable` writes something other than its `toString()`, write it to a `String` yourself and send that.

* `EncoderConfig.defaultCharsetForContentType(charset, contentType)` now only sets the default charset of the given content type. It used to also change the default content charset (`defaultContentCharset()`), so the charset was used for every content type without a charset of its own. For example, after `encoderConfig().defaultCharsetForContentType("UTF-16", ContentType.JSON)` a plain text body was sent as `text/plain; charset=UTF-16` and is now sent as `text/plain; charset=ISO-8859-1`. If you relied on this, also call `defaultContentCharset(..)`:

  ```java
  encoderConfig().defaultCharsetForContentType("UTF-16", ContentType.JSON).defaultContentCharset("UTF-16")
  ```

  The same change was made to `DecoderConfig`, see [Responses](/release-notes/6-2/#responses).

### Form authentication

These changes apply when REST Assured reads the login page to find the form. A form action given to `FormAuthConfig` is still used as it is.

* Form authentication now fails with an `IllegalArgumentException` that names the field when an additional input field given to `FormAuthConfig.withAdditionalField(s)(..)` isn’t on the login page. Such a field used to be sent with the value `[]`. Correct the field name, or remove it from `withAdditionalField(s)(..)`.
* A login form with an empty action (`action=""`) is now posted to the URL of the login page, like a browser does, instead of to `/`.
* A relative form action is now resolved against the URL of the login page (or its `<base href>`), like a browser does. An action without a leading slash used to be resolved against the root, so for example `action="login"` on the page `/secured/page` was posted to `/login` and is now posted to `/secured/login`.

If your server expects the old target in either case, give the form action in `FormAuthConfig`:

```java
given().auth().form("John", "Doe", new FormAuthConfig("/login", "j_username", "j_password")). ..
```

### SSL and certificates

* `auth().certificate(certURL, password)` and `RestAssured.certificate(certURL, password)`, with or without `CertificateAuthSettings`, now use the file at `certURL` as key store, as documented, so the client certificate in it is sent to servers that ask for one (mutual TLS). Before, the file was only used as trust store, which it still is. This means that:

  * A private key in the file is now offered to any server that asks for a client certificate, also where it’s optional (such as nginx with `ssl_verify_client optional`). Such a server may then reject a certificate it doesn’t trust.
  * The private key must have the password of the file.

  To avoid this, or to use the JVM’s default trust store, use the overload that takes a separate trust store and key store. An empty path means no key store, or the default trust store:

  ```java
  // Use the file only as trust store, as before (no client certificate is sent)
  RestAssured.authentication = certificate("/truststore.jks", "password", "", "", certAuthSettings());
  ```

  `certificate(..)` with five arguments returns an `AuthenticationScheme`, so you can also pass it to `RequestSpecBuilder.setAuth(..)`.

* A key store configured without a trust store (with `keyStore(..)` on a request specification, `RequestSpecBuilder`, `RestAssured` or `SSLConfig`) is now used, so REST Assured offers its client certificate to a server that asks for one. Before, the key store was loaded but ignored unless a trust store was configured too, so a server that requires a client certificate rejected the connection. How the server certificate is validated is unchanged (the JVM’s default trust when no trust store is configured). Things to look out for:

  * A server that only requests a client certificate (for example nginx with `ssl_verify_client optional`) and doesn’t trust it now rejects a connection that used to work. If you don’t need a client certificate for that server, remove the `keyStore(..)` call.
  * A key store whose private key can’t be read with the key store password now fails the request instead of being ignored.
  * A key store given as a `KeyStore` without a password, whose private key needs one, fails with an `IllegalArgumentException` that says how to set the password, for example:

  ```java
  given().config(RestAssured.config().sslConfig(sslConfig().keyStore(keyStore).keyStore("password"))). ..
  ```

### Specifications and merging

* Merging a request specification with `spec(..)`, `specification(..)` or `RequestSpecBuilder.addRequestSpecification(..)` no longer resets values that the merged specification never set. The base URI, base path, port, authentication scheme, request body, proxy, HTTP method, path (together with its unnamed path parameters), whether url encoding is enabled, whether a Content-Type is allowed (`noContentType()`) and whether CSRF is disabled (`disableCsrf()`) now survive a merge, and are only overwritten when the merged specification sets them. Values that the merged specification only got from the defaults (such as `RestAssured.baseURI`, `RestAssured.port`, `RestAssured.authentication` or `RestAssured.requestSpecification`) don’t overwrite anything either. For example:

  ```java
  given().auth().oauth2("token").spec(specWithOnlyAHeader). .. // now sends the Authorization header, before it sent none
  given().baseUri("http://host").port(8081).spec(specWithOnlyAHeader). .. // now uses http://host:8081, before it used RestAssured.baseURI and RestAssured.port
  ```

  This also affects a plain `given()`, which merges `RestAssured.requestSpecification`: it now uses the current values of `RestAssured.baseURI`, `RestAssured.port`, `RestAssured.basePath` and `RestAssured.urlEncodingEnabled` instead of the values they had when `RestAssured.requestSpecification` was built, unless that specification set them itself. To remove the authentication with a merged specification, set it to none explicitly:

  ```java
  RequestSpecification noAuth = new RequestSpecBuilder().setAuth(new ExplicitNoAuthScheme()).build();
  ```

* Sending a request directly from a request specification created by `RequestSpecBuilder.build()` (for example `spec.when().get("/x")` or `spec.post()`) now fails with an `IllegalStateException` that tells you to use `given().spec(spec)` or `given(spec)`, instead of a `NullPointerException`. `then()`, `expect()` and `response()` on such a specification also throw this exception, where they returned `null` before. The specification isn’t changed by the failed call.

  ```java
  given(spec).when().get("/x"); // instead of spec.when().get("/x")
  ```

* `given()` no longer writes the session id into the `RestAssured.config` field, or `RestAssured.defaultParser` into the global parser registry. While `RestAssured.sessionId` is set, `RestAssured.config()` returns the config with the session id, but the `RestAssured.config` field doesn’t contain it, also not after a request. So `given().config(RestAssured.config)` no longer sends the static session id:

  ```java
  given().config(RestAssured.config()). .. // instead of given().config(RestAssured.config)
  ```

  Setting `RestAssured.sessionId` or `RestAssured.defaultParser` back to `null` now takes effect without `RestAssured.reset()`. A list returned by `RestAssured.filters()` before `replaceFiltersWith(..)` keeps showing the old filters.

* Sending a request directly from a response specification created by `ResponseSpecBuilder.build()` (for example `responseSpec.when().get("/x")`) now fails with an `IllegalStateException` instead of a `NullPointerException`. `when()`, `given()`, `with()` and `request()` on such a specification also throw this exception, where they returned `null` before. Using the specification in a request, or as `RestAssured.responseSpecification`, works as before.

  ```java
  given(requestSpec, responseSpec).when().get("/x"); // or given().spec(requestSpec).expect().spec(responseSpec)
  ```

* Using a `RequestSpecification` that wasn’t created by REST Assured with `spec(..)` or `specification(..)` on a request specification now fails with an `IllegalArgumentException` instead of a `groovy.lang.MissingMethodException`.

* Using a `ResponseSpecification` that wasn’t created by REST Assured, with `spec(..)` or `specification(..)` on a response specification or as `RestAssured.responseSpecification`, now fails with an `IllegalArgumentException` instead of a `groovy.lang.MissingMethodException`.

### Custom extensions written against internal or Groovy types

These changes only affect you if you implement or call REST Assured’s SPI or `io.restassured.internal` classes, or rely on them being Groovy objects.

* A Groovy closure used as request body now fails with an `IllegalArgumentException`. This could only happen when a custom `ObjectMapper` returned a `Closure` from `serialize(..)`, in which case the closure was run as a builder (a `JsonBuilder` for JSON, a `StreamingMarkupBuilder` for XML and HTML, or with a `Writer` or `OutputStream` for text and binary content). Return a `String`, `byte[]` or `InputStream` from the `ObjectMapper` instead.
* The authentication schemes in `io.restassured.authentication` (`BasicAuthScheme`, `CertAuthScheme`, `ExplicitNoAuthScheme`, `FormAuthScheme`, `NTLMAuthScheme`, `NoAuthScheme`, `OAuth2Scheme`, `OAuthScheme`, `PreemptiveBasicAuthScheme` and `PreemptiveOAuth2HeaderScheme`) and the `AuthenticationScheme` interface are now written in Java, and the classes no longer implement `groovy.lang.GroovyObject`. Their constructors, getters and setters are unchanged. A custom `AuthenticationScheme` written in Java can now get the authentication configuration from `HTTPBuilder.getAuth()`.
* `io.restassured.internal.http.HTTPBuilder`, which a custom `AuthenticationScheme` receives in `authenticate(..)`, no longer uses Groovy closures. Its `get(..)` methods, the `request(..)` overloads that took a `Closure`, `getHandler()` and the `post(..)` and `patch(..)` overloads without a response handler are removed. `post(..)`, `patch(..)` and `request(..)` now take an `HttpResponseHandler` or a `RequestConfigurer`, and response handlers always take two arguments (the response and its parsed content).
* `io.restassured.internal.RestAssuredResponseOptionsGroovyImpl` is removed and its logic now lives in `RestAssuredResponseOptionsImpl`, so `getGroovyResponse()`, `setGroovyResponse(..)` and the protected `groovyResponse` field of `RestAssuredResponseOptionsImpl` are gone. This affects code that calls these methods or subclasses the internal response classes. A subclass that overrides a method such as `asString()` now also sees that override used by `path(..)`, `jsonPath()`, `as(..)` and the other methods that read the body.
* `io.restassured.assertion.HeaderMatcher`, `DetailedCookieAssertion`, `ResponseTimeMatcher` and `StreamVerifier` are now written in Java and no longer implement `groovy.lang.GroovyObject`. `HeaderMatcher.validateHeader(..)`, `DetailedCookieAssertion.validateCookies(..)` and `ResponseTimeMatcher.validate(..)` now return `Map<String, Object>` instead of `Object`, `HeaderMatcher.validateHeader(..)` takes a `Response`, and `HeaderMatcher.getMatcher()` and `get/setResponseAwareMatcher(..)` are now generically typed (`Matcher<?>` and `ResponseAwareMatcher<Response>`).
* `io.restassured.internal.matcher.xml.XmlXsdMatcher` (the return type of `RestAssuredMatchers.matchesXsd(..)`) and `XmlDtdMatcher` are now written in Java and no longer implement `groovy.lang.GroovyObject`.

### Responses

* `path(..)` on a response with an HTML content type (for example `get("/page.html").path("html.head.title")` or `then().extract().path(..)`) now returns the value the path points to, like it does for JSON and XML responses and like `body("html.head.title", ..)` does. Before, it returned the `XmlPath` itself, so extracting the value to a `String` failed with a `ClassCastException`. Use `htmlPath()` to get an `XmlPath` for an HTML response:

  ```java
  String title = get("/page.html").path("html.head.title");
  XmlPath html = get("/page.html").htmlPath(); // instead of get("/page.html").path(..) to get the XmlPath
  ```

* `DecoderConfig.defaultCharsetForContentType(charset, contentType)` now only sets the default charset of the given content type. It used to also change the default content charset (`defaultContentCharset()`), so a response without a charset in its content-type was decoded with that charset even when its content type had no charset of its own. For example, after `decoderConfig().defaultCharsetForContentType("UTF-16", ContentType.JSON)` a `text/plain` response without a charset was decoded as UTF-16 and is now decoded with the default content charset. If you relied on this, also call `defaultContentCharset(..)`:

  ```java
  decoderConfig().defaultCharsetForContentType("UTF-16", ContentType.JSON).defaultContentCharset("UTF-16")
  ```

* `matchesXsdInClasspath(..)` and `matchesDtdInClasspath(..)` (in `RestAssuredMatchers`, `RestAssuredMockMvcMatchers` and `RestAssuredWebTestClientMatchers`) now fail with an `IllegalArgumentException` saying that the XSD or DTD couldn’t be found in classpath, instead of a `groovy.lang.GroovyRuntimeException` (“Ambiguous method overloading”). The XSD and DTD matchers now also fail with an `IllegalArgumentException` when asked to match something that isn’t a `String`, for example `body("some.path", matchesXsd(..))` where the path returns an element that has child elements, instead of a Groovy exception.

## Other changes

* Upgraded the dependencies of the published modules. scala-library in `scala-support` goes from 2.13.0 to 2.13.18, which fixes CVE-2022-36944. Also upgraded: scala3-library_3 in `scala-extensions` to 3.3.8, Jackson 2 to 2.22.3, Jackson 3 (`tools.jackson`) to 3.2.3, Gson to 2.14.0, Guava in `json-schema-validator` to 33.7.2-jre, commons-lang3 to 3.21.0, Yasson to 3.0.5 (now with its new group id `org.eclipse.yasson`), Parsson to 1.1.9, Johnzon to 2.2.0 and jaxb-impl to 2.3.9 ([#1986](https://github.com/rest-assured/rest-assured/pull/1986)).

* Fixed `spring-web-test-client-kotlin-extensions` bringing `jakarta.servlet-api`, `jakarta.jakartaee-web-api` and about 20 other Jakarta EE API jars to your runtime classpath. They are now `provided`, like in `spring-mock-mvc-kotlin-extensions` ([#1992](https://github.com/rest-assured/rest-assured/pull/1992)).

* Upgraded Groovy from 5.0.3 to 5.0.8 and Apache HttpClient (`httpclient` and `httpmime`) from 4.5.13 to 4.5.14 ([#1971](https://github.com/rest-assured/rest-assured/issues/1971)).

* Fixed PATCH requests with form parameters or multipart content, which were sent without their query parameters ([#1001](https://github.com/rest-assured/rest-assured/issues/1001)).

* Fixed sending a `String` body or form parameters with `noContentType()`, which failed unless an expected response content type was set. The body is now sent as text in the default content charset, so the `encodeContentTypeAs("*/*", ContentType.TEXT)` workaround is no longer needed ([#1947](https://github.com/rest-assured/rest-assured/issues/1947)).

* Fixed a request hanging forever when its path contains a `{` that is never closed, for example `get("/x{b")`. An unclosed `{` is now kept as literal text ([#1935](https://github.com/rest-assured/rest-assured/issues/1935)).

* Fixed a `byte[]` multipart being sent empty the second time a request specification is used ([#1938](https://github.com/rest-assured/rest-assured/issues/1938)).

* Fixed a multipart boundary that contains `=`, for example a JavaMail-style boundary such as `----=_Part_0_123`, being replaced or cut short. The boundary is now used as given ([#1948](https://github.com/rest-assured/rest-assured/issues/1948)).

* Fixed `multiPart(String, Object)` with a `String` and no request content type. It now adds a `text/plain` part ([#1930](https://github.com/rest-assured/rest-assured/issues/1930)).

* Fixed `keyStore(KeyStore)` on a request specification and `RequestSpecBuilder.setKeyStore(KeyStore)`, which always failed. `SSLConfig` gets a `keyStore(KeyStore)` method. `relaxedHTTPSValidation()` only uses a key store given by path, not a `KeyStore` object ([#1930](https://github.com/rest-assured/rest-assured/issues/1930)).

* Form authentication fixes:

  * Requests with path parameters, for example `given().auth().form("John", "Doe").get("/secured/{id}", 1)`, no longer fail with “Invalid number of path parameters”, and the login page is no longer URL encoded twice ([#1940](https://github.com/rest-assured/rest-assured/issues/1940)).
  * A login form without an action attribute is posted to the URL of the login page instead of failing with a `NullPointerException` ([#1941](https://github.com/rest-assured/rest-assured/issues/1941)).
  * A `SessionFilter` subclass is passed on to the login request ([#1941](https://github.com/rest-assured/rest-assured/issues/1941)).
  * An additional field whose input tag has no value attribute is sent without a value instead of failing ([#1921](https://github.com/rest-assured/rest-assured/issues/1921)).
  * A form action read from the login page is no longer URL encoded twice, and an absolute form action’s path and query are posted to the host of the request ([#1954](https://github.com/rest-assured/rest-assured/issues/1954)).

* Fixed `CsrfConfig.csrfMetaTagName(..)`, which also set the CSRF input field name ([#1945](https://github.com/rest-assured/rest-assured/issues/1945)).

* Fixed `LogConfig.defaultStream(..)`, which always turned pretty printing back on ([#1946](https://github.com/rest-assured/rest-assured/issues/1946)).

* Fixed merging a request specification that has unnamed path parameters, for example the one a filter receives for `get("/users/{id}", 1)` ([#1931](https://github.com/rest-assured/rest-assured/issues/1931)).

* Fixed a root path with more than one placeholder left for a later `withArgs(..)`, which failed with a `MissingFormatArgumentException`. `body(withArgs(..), matcher)` no longer adds a trailing dot to the path in failure messages ([#1949](https://github.com/rest-assured/rest-assured/issues/1949)).

* Fixed `FilterContext.send(..)` for TRACE and custom HTTP methods such as `request("PURGE", "/x")` ([#1929](https://github.com/rest-assured/rest-assured/issues/1929)).

* Fixed `getResponseContentType()` on the response specification that filters receive, which always failed with a `StackOverflowError` ([#1928](https://github.com/rest-assured/rest-assured/issues/1928)).

* Fixed `asByteArray()` on a response whose body was replaced by an `InputStream`, for example by a filter ([#1926](https://github.com/rest-assured/rest-assured/issues/1926)).

* Fixed `sessionId()` on Spring MockMvc, Spring WebTestClient and `ResponseBuilder` responses, and `header(name)` on a response without headers, which now returns `null` ([#1944](https://github.com/rest-assured/rest-assured/issues/1944)).

* Fixed a `ResponseAwareMatcher` in a static `RestAssuredMockMvc.responseSpecification` or `RestAssuredWebTestClient.responseSpecification` failing when it calls `path(..)`, and ignoring the configured session id name ([#1944](https://github.com/rest-assured/rest-assured/issues/1944)).

* XSD and DTD matcher fixes:

  * `matchesDtd(URL)` always failed with a `GroovyCastException` ([#1920](https://github.com/rest-assured/rest-assured/issues/1920)).
  * The same matcher can now be used more than once, for example in a shared `ResponseSpecification`. An `InputStream` or `Reader` given to these matchers is now read and closed when the matcher is created ([#1936](https://github.com/rest-assured/rest-assured/issues/1936)).
  * `matchesXsdInClasspath(..)` and `matchesDtdInClasspath(..)` also look in the class loader that loaded REST Assured, so they work on threads without a usable context class loader ([#1937](https://github.com/rest-assured/rest-assured/issues/1937)).

* Fixed JsonPath and JSON body expectations failing with `ClassNotFoundException: groovy.lang.Script` in an OSGi container, or whenever the thread context class loader can’t see Groovy ([#1933](https://github.com/rest-assured/rest-assured/issues/1933)).

* Non-`String` names and values that used to fail with a Groovy exception are now converted to their string form, so `1` becomes `"1"`: parameter names in `params(Map)`, `queryParams(Map)`, `formParams(Map)` and `pathParams(Map)` ([#1927](https://github.com/rest-assured/rest-assured/issues/1927)), cookie values in `cookies(..)` ([#1930](https://github.com/rest-assured/rest-assured/issues/1930)), header and cookie names in `headers(..)` and `cookies(..)` ([#1931](https://github.com/rest-assured/rest-assured/issues/1931)), header names in header expectations ([#1919](https://github.com/rest-assured/rest-assured/issues/1919)) and body expectation paths ([#1928](https://github.com/rest-assured/rest-assured/issues/1928)).

* A list given as path, or as path arguments to `body(..)`, `rootPath(..)`, `root(..)` or `appendRootPath(..)`, whose elements aren’t all created by `withArgs(..)`, now fails with an `IllegalArgumentException` ([#1928](https://github.com/rest-assured/rest-assured/issues/1928)). A `CertAuthScheme` key store or trust store path that is neither a `String` nor a `File` also fails with an `IllegalArgumentException` ([#1925](https://github.com/rest-assured/rest-assured/issues/1925)).

See [change log](https://github.com/rest-assured/rest-assured/raw/master/changelog.txt) for more details.