testcontainers/testcontainers-java · error · ScriptParseException

Missing block comment end delimiter…

Error message

Missing block comment end delimiter [blockCommentEndDelimiter].

What it means

ScriptScanner parses SQL init scripts and, upon encountering a block comment start delimiter (default /*), scans for the matching end delimiter (default */). If none exists before end of script, it throws ScriptUtils.ScriptParseException. The script file is malformed: a multi-line comment was opened but never closed.

Solutions

  1. Open the script at the reported resource and close every /* with */.
  2. If the script intentionally uses a different comment terminator, pass matching blockCommentStartDelimiter/blockCommentEndDelimiter to executeDatabaseScript.
  3. Lint the SQL files in CI to catch unbalanced comment delimiters before runtime.

Example fix

// before (script.sql)
/* TODO: fix this comment
INSERT INTO users VALUES (1);
// after (script.sql)
/* TODO: fix this comment */
INSERT INTO users VALUES (1);
Defensive patterns

Strategy: validation

Validate before calling

String script = Files.readString(Path.of("src/test/resources/init.sql"));
if (countOccurrences(script, "/*") != countOccurrences(script, "*/")) {
    throw new IllegalStateException("Unbalanced block comment delimiters in init.sql");
}

Try / catch

try {
    ScriptUtils.executeDatabaseScript(delegate, path, script);
} catch (ScriptUtils.ScriptParseException e) {
    if (e.getMessage().contains("Missing block comment end delimiter")) {
        // surface the offending resource in test failure output
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing an init script via withInitScript/executeDatabaseScript that contains '/*' with no matching '*/', or a custom blockCommentEndDelimiter that doesn't match what the script uses.

Common situations: Hand-edited SQL files where a comment close was deleted; copying scripts across dialects with different comment conventions; passing a wrong end-delimiter argument to executeDatabaseScript.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at modules/database-commons/src/main/java/org/testcontainers/ext/ScriptScanner.java:86

            if (m.find(offset)) {
                currentMatch = commentPrefix + script.substring(offset, m.end());
                offset = m.end();
            } else {
                currentMatch = commentPrefix + script.substring(offset);
                offset = script.length();
            }
            return true;
        }
        return false;
    }

    private boolean matchesMultilineComment() {
        /* Matches from blockCommentStartDelimiter to the next blockCommentEndDelimiter.
         * Error, if blockCommentEndDelimiter is not found. */
        if (matches(blockCommentStartDelimiter)) {
            int end = script.indexOf(blockCommentEndDelimiter, offset);
            if (end < 0) {
                throw new ScriptUtils.ScriptParseException(
                    String.format("Missing block comment end delimiter [%s].", blockCommentEndDelimiter),
                    resource
                );
            }
            end += blockCommentEndDelimiter.length();
            currentMatch = blockCommentStartDelimiter + script.substring(offset, end);
            offset = end;
            return true;
        }
        return false;
    }

    private boolean matchesQuotedString(final char quote) {
        if (script.charAt(offset) == quote) {
            boolean escaped = false;
            for (int i = offset + 1; i < script.length(); i++) {
                char c = script.charAt(i);
                if (escaped) {

View on GitHub (pinned to 8e549514e3)