eclipse-vertx/vert.x · error · RuntimeException

Missing -----END ----- delimiter

Error message

Missing -----END ----- delimiter

What it means

KeyStoreHelper.loadPems() scans a PEM buffer with regexes for BEGIN/END blocks. If a BEGIN ... block has no matching END line after it, a RuntimeException 'Missing -----END <type>----- delimiter' is thrown. This means the PEM text is truncated or malformed.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/net/impl/KeyStoreHelper.java:362

      }
    }
    return keyStore;
  }

  private static <P> List<P> loadPems(Buffer data, BiFunction<String, byte[], Collection<P>> pemFact) throws IOException {
    String pem = data.toString();
    List<P> pems = new ArrayList<>();
    Matcher beginMatcher = BEGIN_PATTERN.matcher(pem);
    Matcher endMatcher = END_PATTERN.matcher(pem);
    while (true) {
      boolean begin = beginMatcher.find();
      if (!begin) {
        break;
      }
      String beginDelimiter = beginMatcher.group(1);
      boolean end = endMatcher.find();
      if (!end) {
        throw new RuntimeException("Missing -----END " + beginDelimiter + "----- delimiter");
      } else {
        String endDelimiter = endMatcher.group(1);
        if (!beginDelimiter.equals(endDelimiter)) {
          throw new RuntimeException("Missing -----END " + beginDelimiter + "----- delimiter");
        } else {
          String content = pem.substring(beginMatcher.end(), endMatcher.start());
          content = content.replaceAll("\\s", "");
          if (content.length() == 0) {
            throw new RuntimeException("Empty pem file");
          }
          Collection<P> pemItems = pemFact.apply(endDelimiter, Base64.getDecoder().decode(content));
          pems.addAll(pemItems);
        }
      }
    }
    return pems;
  }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Check the file is complete: the last line must be -----END <TYPE>-----; re-download or re-copy the PEM.
  2. Validate with: openssl x509 -in cert.pem -noout (or openssl pkey -in key.pem -noout) — it fails on truncated files.
  3. If concatenating multiple PEMs, ensure each block has both BEGIN and END lines.
  4. Check the secret/configmap was fully mounted (kubectl get secret -o yaml and compare lengths).

Example fix

// before (truncated)
-----BEGIN CERTIFICATE-----
MIID... 
// after
-----BEGIN CERTIFICATE-----
MIID...
-----END CERTIFICATE-----
Defensive patterns

Strategy: validation

Validate before calling

String pem = Files.readString(Path.of(pemPath)).trim();
if (!pem.matches("(?s)-----BEGIN [^-]+-----.*-----END [^-]+-----"))
    throw new IllegalStateException("PEM file incomplete (missing END delimiter): " + pemPath);

Type guard

boolean isCompletePem(String s) {
  if (s == null) return false;
  long begin = s.split("-----BEGIN", -1).length - 1;
  long end = s.split("-----END", -1).length - 1;
  return begin > 0 && begin == end;
}

Prevention

When it happens

Trigger: Passing a truncated PEM file (cut-off transfer, partial secret mount) to key/cert options; PEM content programmatically split so the closing END line is missing; extra BEGIN line without a body/end.

Common situations: Secrets truncated by missing final newline handling in CI; copy-paste dropping the last line; HAProxy/nginx config snippets inserted mid-PEM.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/59ce7eed01993b06. Report an issue: GitHub.