{"record":{"id":"0e988706b9f4abfc","repo":"testcontainers/testcontainers-java","slug":"the-character-must-be-included","errorCode":null,"errorMessage":"The '?' character must be included","messagePattern":"The '\\?' character must be included","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java","lineNumber":316,"sourceCode":"\n    /**\n     * Template method for constructing the JDBC URL to be used for creating {@link Connection}s.\n     * This should be overridden if the JDBC URL and query string concatenation or URL string\n     * construction needs to be different to normal.\n     *\n     * @param queryString query string parameters that should be appended to the JDBC connection URL.\n     *                    The '?' character must be included\n     * @return a full JDBC URL including queryString\n     */\n    protected String constructUrlForConnection(String queryString) {\n        String baseUrl = getJdbcUrl();\n\n        if (\"\".equals(queryString)) {\n            return baseUrl;\n        }\n\n        if (!queryString.startsWith(\"?\")) {\n            throw new IllegalArgumentException(\"The '?' character must be included\");\n        }\n\n        return baseUrl.contains(\"?\")\n            ? baseUrl + QUERY_PARAM_SEPARATOR + queryString.substring(1)\n            : baseUrl + queryString;\n    }\n\n    protected String constructUrlParameters(String startCharacter, String delimiter) {\n        return constructUrlParameters(startCharacter, delimiter, StringUtils.EMPTY);\n    }\n\n    protected String constructUrlParameters(String startCharacter, String delimiter, String endCharacter) {\n        String urlParameters = \"\";\n        if (!this.urlParameters.isEmpty()) {\n            String additionalParameters =\n                this.urlParameters.entrySet().stream().map(Object::toString).collect(Collectors.joining(delimiter));\n            urlParameters = startCharacter + additionalParameters + endCharacter;\n        }","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/testcontainers/testcontainers-java/blob/8e549514e3f01c57d70546fbb8599d138f3903e5/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java#L298-L334","documentation":"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.","triggerScenarios":"Calling createConnection(\"key=value\") (or url(...) paths) with a query string lacking the leading '?' character.","commonSituations":"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.","solutions":["Prefix the query string with '?', e.g. createConnection(\"?ssl=true\")","Pass an empty string if no parameters are needed","Build the query via a helper that always prepends '?' when non-empty"],"exampleFix":"// before\ncontainer.createConnection(\"ssl=true&connectTimeout=30\");\n// after\ncontainer.createConnection(\"?ssl=true&connectTimeout=30\");","handlingStrategy":"validation","validationCode":"String qs = params.isEmpty() ? \"\" : \"?\" + String.join(\"&\", params);","typeGuard":"static String ensureQueryString(String s) { return (s == null || s.isEmpty() || s.startsWith(\"?\")) ? s : \"?\" + s; }","tryCatchPattern":"try { url = container.createConnection(qs); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"'?' character\")) { /* re-call with '?'+qs */ } }","preventionTips":["Never pass raw key=value pairs without the leading '?'","Use a helper that normalizes empty and non-empty query strings"],"tags":["jdbc","url-format","invalid-argument"],"backgroundTag":"invalid-url-format","analyzedSha":"8e549514e3f01c57d70546fbb8599d138f3903e5","analyzedAt":"2026-09-12T14:56:41.227Z","contentChangedAt":"2026-09-12T14:56:41.227Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}