{"record":{"id":"59ce7eed01993b06","repo":"eclipse-vertx/vert.x","slug":"missing-end-delimiter","errorCode":null,"errorMessage":"Missing -----END ----- delimiter","messagePattern":"Missing -----END ----- delimiter","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/net/impl/KeyStoreHelper.java","lineNumber":362,"sourceCode":"      }\n    }\n    return keyStore;\n  }\n\n  private static <P> List<P> loadPems(Buffer data, BiFunction<String, byte[], Collection<P>> pemFact) throws IOException {\n    String pem = data.toString();\n    List<P> pems = new ArrayList<>();\n    Matcher beginMatcher = BEGIN_PATTERN.matcher(pem);\n    Matcher endMatcher = END_PATTERN.matcher(pem);\n    while (true) {\n      boolean begin = beginMatcher.find();\n      if (!begin) {\n        break;\n      }\n      String beginDelimiter = beginMatcher.group(1);\n      boolean end = endMatcher.find();\n      if (!end) {\n        throw new RuntimeException(\"Missing -----END \" + beginDelimiter + \"----- delimiter\");\n      } else {\n        String endDelimiter = endMatcher.group(1);\n        if (!beginDelimiter.equals(endDelimiter)) {\n          throw new RuntimeException(\"Missing -----END \" + beginDelimiter + \"----- delimiter\");\n        } else {\n          String content = pem.substring(beginMatcher.end(), endMatcher.start());\n          content = content.replaceAll(\"\\\\s\", \"\");\n          if (content.length() == 0) {\n            throw new RuntimeException(\"Empty pem file\");\n          }\n          Collection<P> pemItems = pemFact.apply(endDelimiter, Base64.getDecoder().decode(content));\n          pems.addAll(pemItems);\n        }\n      }\n    }\n    return pems;\n  }\n","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/net/impl/KeyStoreHelper.java#L344-L380","documentation":"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.","triggerScenarios":"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.","commonSituations":"Secrets truncated by missing final newline handling in CI; copy-paste dropping the last line; HAProxy/nginx config snippets inserted mid-PEM.","solutions":["Check the file is complete: the last line must be -----END <TYPE>-----; re-download or re-copy the PEM.","Validate with: openssl x509 -in cert.pem -noout (or openssl pkey -in key.pem -noout) — it fails on truncated files.","If concatenating multiple PEMs, ensure each block has both BEGIN and END lines.","Check the secret/configmap was fully mounted (kubectl get secret -o yaml and compare lengths)."],"exampleFix":"// before (truncated)\n-----BEGIN CERTIFICATE-----\nMIID... \n// after\n-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----","handlingStrategy":"validation","validationCode":"String pem = Files.readString(Path.of(pemPath)).trim();\nif (!pem.matches(\"(?s)-----BEGIN [^-]+-----.*-----END [^-]+-----\"))\n    throw new IllegalStateException(\"PEM file incomplete (missing END delimiter): \" + pemPath);","typeGuard":"boolean isCompletePem(String s) {\n  if (s == null) return false;\n  long begin = s.split(\"-----BEGIN\", -1).length - 1;\n  long end = s.split(\"-----END\", -1).length - 1;\n  return begin > 0 && begin == end;\n}","tryCatchPattern":null,"preventionTips":["Ensure copy/paste and templating preserve the full file including the last line","Checksum PEM files in CI to catch truncated transfers","Avoid manual editing of concatenated PEMs; regenerate from source","Verify with openssl before deploying"],"tags":["ssl","pem","malformed-file"],"backgroundTag":"invalid-pem-file","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}