{"record":{"id":"035738cf44337352","repo":"apache/pulsar","slug":"tlspolicy-field-field-is-set-but-is-not-valid","errorCode":null,"errorMessage":"TlsPolicy field '${field}' is set but is not valid for format ${format}; use the fields matching the chosen format (PEM: trustCertsFilePath/certificateFilePath/keyFilePath; KEYSTORE: trustStorePath/keyStorePath/... with keyStoreType/trustStoreType), or set the format to match the material.","messagePattern":"TlsPolicy field '(.+?)' is set but is not valid for format (.+?); use the fields matching the chosen format \\(PEM: trustCertsFilePath/certificateFilePath/keyFilePath; KEYSTORE: trustStorePath/keyStorePath/\\.\\.\\. with keyStoreType/trustStoreType\\), or set the format to match the material\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-tls-factory-api/src/main/java/org/apache/pulsar/tls/TlsPolicy.java","lineNumber":584,"sourceCode":"\n        private void validateFormatConsistency() {\n            if (format == Format.PEM) {\n                rejectForFormat(\"trustStorePath\", trustStorePath);\n                rejectForFormat(\"trustStorePassword\", trustStorePassword);\n                rejectForFormat(\"keyStorePath\", keyStorePath);\n                rejectForFormat(\"keyStorePassword\", keyStorePassword);\n                rejectForFormat(\"keyStoreType\", keyStoreType);\n                rejectForFormat(\"trustStoreType\", trustStoreType);\n            } else { // Format.KEYSTORE\n                rejectForFormat(\"trustCertsFilePath\", trustCertsFilePath);\n                rejectForFormat(\"certificateFilePath\", certificateFilePath);\n                rejectForFormat(\"keyFilePath\", keyFilePath);\n            }\n        }\n\n        private void rejectForFormat(String field, String value) {\n            if (value != null && !value.isBlank()) {\n                throw new IllegalArgumentException(\"TlsPolicy field '\" + field + \"' is set but is not valid for \"\n                        + \"format \" + format + \"; use the fields matching the chosen format (PEM: \"\n                        + \"trustCertsFilePath/certificateFilePath/keyFilePath; KEYSTORE: \"\n                        + \"trustStorePath/keyStorePath/... with keyStoreType/trustStoreType), or set the format \"\n                        + \"to match the material.\");\n            }\n        }\n    }\n}\n","sourceCodeStart":566,"sourceCodeEnd":593,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-tls-factory-api/src/main/java/org/apache/pulsar/tls/TlsPolicy.java#L566-L593","documentation":"TlsPolicy.validateFormatConsistency checks that key material fields match the chosen format: PEM fields (trustCertsFilePath, certificateFilePath, keyFilePath) must be empty when format is KEYSTORE, and KEYSTORE fields (trustStorePath, keyStorePath, keyStoreType, trustStoreType, etc.) must be empty when format is PEM. rejectForFormat throws IllegalArgumentException when a field is populated for the wrong format, preventing a policy that silently ignores or misinterprets TLS material.","triggerScenarios":"Building a TlsPolicy with format=PEM while any of trustStorePath/keyStorePath/keyStoreType/trustStoreType etc. is set, or format=KEYSTORE while any of trustCertsFilePath/certificateFilePath/keyFilePath is set — the rejectForFormat calls in validateFormatConsistency fire during TlsPolicy construction/build.","commonSituations":"Migrating from PEM to keystore config and leaving the old PEM paths behind; copy-pasting a TLS config template that includes both styles; an operator adding keyStoreType for 'documentation' while still using PEM files; tools merging two config layers that each set different TLS styles.","solutions":["Remove the keyStore*/trustStore* fields from the config when format is PEM (or vice versa — drop trustCertsFilePath/certificateFilePath/keyFilePath when format is KEYSTORE)","Set tlsFormat/PolicyFormat to KEYSTORE if the actual material is .jks/.p12 stores, or PEM if the material is .crt/.key/.pem files","Audit merged configuration layers so only one TLS material style is populated","Add a config validation step before deployment that instantiates the TlsPolicy to fail fast on mixed formats"],"exampleFix":"// before\nformat=PEM\nkeyStorePath=/path/to/keystore.jks   // leftover from KEYSTORE config\ntrustCertsFilePath=/path/to/ca.pem\n\n// after\nformat=PEM\ntrustCertsFilePath=/path/to/ca.pem","handlingStrategy":"validation","validationCode":"void validateTlsMaterial(String format, String trustCertsFilePath, String certificateFilePath, String keyFilePath,\n                         String trustStorePath, String keyStorePath) {\n    boolean hasPem = isSet(trustCertsFilePath) || isSet(certificateFilePath) || isSet(keyFilePath);\n    boolean hasKeystore = isSet(trustStorePath) || isSet(keyStorePath);\n    if (\"PEM\".equalsIgnoreCase(format) && hasKeystore) {\n        throw new IllegalArgumentException(\"KEYSTORE fields set but format is PEM\");\n    }\n    if (\"KEYSTORE\".equalsIgnoreCase(format) && hasPem) {\n        throw new IllegalArgumentException(\"PEM fields set but format is KEYSTORE\");\n    }\n}\nprivate boolean isSet(String s) { return s != null && !s.isBlank(); }","typeGuard":"boolean isTlsFormatConsistent(String format, boolean pemMaterialSet, boolean keystoreMaterialSet) {\n    if (\"PEM\".equalsIgnoreCase(format)) return !keystoreMaterialSet;\n    if (\"KEYSTORE\".equalsIgnoreCase(format)) return !pemMaterialSet;\n    return false;\n}","tryCatchPattern":"try {\n    TlsPolicy policy = buildTlsPolicy();\n    policy.validateFormatConsistency(); // or rely on constructor validation\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"TlsPolicy field\")) {\n        LOG.error(\"TLS material does not match configured format: {}\", e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Keep only one TLS material style (PEM or KEYSTORE) populated in config, matching the format field","When migrating between PEM and keystore, delete the obsolete fields rather than leaving them set","Run a startup-time TlsPolicy validation in CI against production-like config","Document which fields belong to PEM vs KEYSTORE formats in your deployment templates"],"tags":["tls","configuration","validation","pem","keystore"],"backgroundTag":"tls-config-mismatch","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}