testcontainers/testcontainers-java · error · IllegalStateException

message: response, body=body

Error message

message: response, body=body

What it means

checkSuccessfulResponse() is Testcontainers' guard for Couchbase REST calls made during container configuration. When the management API returns a non-success status, it throws IllegalStateException containing the request message, the HTTP response object, and (when readable) the response body, so the actual server-side failure reason is surfaced.

Solutions

  1. Read the 'body=' part of the message — it contains Couchbase's own error explanation (e.g. quota too small, service unsupported).
  2. Verify quotas meet service minimums and services are supported by your image edition.
  3. Use a fresh container/volume; avoid reusing state from previous runs that conflict with rename/external-port configuration.
  4. Ensure all with* configuration happens before container.start().

Example fix

// before
container.withServiceQuota(CouchbaseService.SEARCH, 100).start(); // server rejects quota
// after
container.withServiceQuota(CouchbaseService.SEARCH, CouchbaseService.SEARCH.getMinimumQuotaMb()).start();
Defensive patterns

Strategy: try-catch

Validate before calling

// before start(): validate all quotas and services
for (Map.Entry<CouchbaseService,Integer> e : quotas.entrySet()) {
    if (!e.getKey().hasQuota() || e.getValue() < e.getKey().getMinimumQuotaMb()) {
        throw new IllegalArgumentException("bad quota for " + e.getKey());
    }
}

Try / catch

try {
    container.start();
} catch (IllegalStateException e) {
    // message embeds 'body=<server error>' — parse/log it for the root cause
    String body = e.getMessage().replaceAll(".*body=", "");
    logger.error("Couchbase config API rejected a call: {}", body, e);
    throw e;
}

Prevention

When it happens

Trigger: Any configuration REST call failing: renameNode, initializeServices (unsupported service for edition), setMemoryQuotas (quota below server minimum), configureAdminUser, configureExternalPorts, configureIndexer — i.e. any 4xx/5xx from the Couchbase management API during startup.

Common situations: Requesting a service the edition doesn't support; quota conflicts between buckets/services; reusing a container volume with conflicting node names; calling setters after the container already started (partially configured).

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/ca86c6217243ccf8. Report an issue: GitHub.

Appendix: source

Thrown at modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseContainer.java:794

    /**
     * Helper method to check if the response is successful and release the body if needed.
     *
     * @param response the response to check.
     * @param message the message that should be part of the exception of not successful.
     */
    private void checkSuccessfulResponse(final Response response, final String message) {
        if (!response.isSuccessful()) {
            String body = null;
            if (response.body() != null) {
                try {
                    body = response.body().string();
                } catch (IOException e) {
                    logger().debug("Unable to read body of response: {}", response, e);
                }
            }

            throw new IllegalStateException(message + ": " + response + ", body=" + (body == null ? "<null>" : body));
        }
    }

    /**
     * Checks if already running and if so raises an exception to prevent too-late setters.
     */
    private void checkNotRunning() {
        if (isRunning()) {
            throw new IllegalStateException("Setter can only be called before the container is running");
        }
    }

    /**
     * Helper method to perform a request against a couchbase server HTTP endpoint.
     *
     * @param port the (unmapped) original port that should be used.
     * @param path the relative http path.
     * @param method the http method to use.

View on GitHub (pinned to 8e549514e3)