testcontainers/testcontainers-java · error · IllegalArgumentException

The '?' character must be included

Error message

The '?' character must be included

What it means

constructUrlForConnection(String queryString) appends an optional query string to the base JDBC URL, and documents/enforces that a non-empty query string must start with '?'. A bare 'key=value' string without the leading question mark triggers this IllegalArgumentException to prevent malformed URLs.

Solutions

  1. Prefix the query string with '?', e.g. createConnection("?ssl=true")
  2. Pass an empty string if no parameters are needed
  3. Build the query via a helper that always prepends '?' when non-empty

Example fix

// before
container.createConnection("ssl=true&connectTimeout=30");
// after
container.createConnection("?ssl=true&connectTimeout=30");
Defensive patterns

Strategy: validation

Validate before calling

String qs = params.isEmpty() ? "" : "?" + String.join("&", params);

Type guard

static String ensureQueryString(String s) { return (s == null || s.isEmpty() || s.startsWith("?")) ? s : "?" + s; }

Try / catch

try { url = container.createConnection(qs); } catch (IllegalArgumentException e) { if (e.getMessage().contains("'?' character")) { /* re-call with '?'+qs */ } }

Prevention

When it happens

Trigger: Calling createConnection("key=value") (or url(...) paths) with a query string lacking the leading '?' character.

Common situations: Manually building parameter strings like 'ssl=true' without '?'; template concatenation that strips the question mark; copying URL fragments from documentation that include the base URL's '?' already.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java:316

    /**
     * Template method for constructing the JDBC URL to be used for creating {@link Connection}s.
     * This should be overridden if the JDBC URL and query string concatenation or URL string
     * construction needs to be different to normal.
     *
     * @param queryString query string parameters that should be appended to the JDBC connection URL.
     *                    The '?' character must be included
     * @return a full JDBC URL including queryString
     */
    protected String constructUrlForConnection(String queryString) {
        String baseUrl = getJdbcUrl();

        if ("".equals(queryString)) {
            return baseUrl;
        }

        if (!queryString.startsWith("?")) {
            throw new IllegalArgumentException("The '?' character must be included");
        }

        return baseUrl.contains("?")
            ? baseUrl + QUERY_PARAM_SEPARATOR + queryString.substring(1)
            : baseUrl + queryString;
    }

    protected String constructUrlParameters(String startCharacter, String delimiter) {
        return constructUrlParameters(startCharacter, delimiter, StringUtils.EMPTY);
    }

    protected String constructUrlParameters(String startCharacter, String delimiter, String endCharacter) {
        String urlParameters = "";
        if (!this.urlParameters.isEmpty()) {
            String additionalParameters =
                this.urlParameters.entrySet().stream().map(Object::toString).collect(Collectors.joining(delimiter));
            urlParameters = startCharacter + additionalParameters + endCharacter;
        }

View on GitHub (pinned to 8e549514e3)