{"record":{"id":"4650e4a75ecf0b01","repo":"provectus/kafka-ui","slug":"you-can-t-provide-both-fieldnames-fieldsnamepatt","errorCode":null,"errorMessage":"You can't provide both fieldNames & fieldsNamePattern for masking","messagePattern":"You can't provide both fieldNames & fieldsNamePattern for masking","errorType":"validation","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/masking/policies/FieldsSelector.java","lineNumber":13,"sourceCode":"package com.provectus.kafka.ui.service.masking.policies;\n\nimport com.provectus.kafka.ui.config.ClustersProperties;\nimport com.provectus.kafka.ui.exception.ValidationException;\nimport java.util.regex.Pattern;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\n\ninterface FieldsSelector {\n\n  static FieldsSelector create(ClustersProperties.Masking property) {\n    if (StringUtils.hasText(property.getFieldsNamePattern()) && !CollectionUtils.isEmpty(property.getFields())) {\n      throw new ValidationException(\"You can't provide both fieldNames & fieldsNamePattern for masking\");\n    }\n    if (StringUtils.hasText(property.getFieldsNamePattern())) {\n      Pattern pattern = Pattern.compile(property.getFieldsNamePattern());\n      return f -> pattern.matcher(f).matches();\n    }\n    if (!CollectionUtils.isEmpty(property.getFields())) {\n      return f -> property.getFields().contains(f);\n    }\n    //no pattern, no field names - mean all fields should be masked\n    return fieldName -> true;\n  }\n\n  boolean shouldBeMasked(String fieldName);\n\n}\n","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/provectus/kafka-ui/blob/83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/masking/policies/FieldsSelector.java#L1-L29","documentation":"FieldsSelector.create() builds the predicate that decides which fields a masking policy applies to. A policy may select fields either by an explicit list of names (fields) or by a regex (fieldsNamePattern), never both. When both are set in the ClustersProperties.Masking config, the selector cannot decide which rule wins, so it throws this ValidationException at startup/config time.","triggerScenarios":"A kafka-ui clusters config defines a masking entry where both `fields` (non-empty list) and `fieldsNamePattern` (non-blank string) are populated; FieldsSelector.create() is then invoked when the masking policy is constructed.","commonSituations":"Copy-pasting an example masking config and adding a regex on top of existing field names; merging two partial masking configs; a Helm values overlay that appends fieldsNamePattern without removing fields.","solutions":["Remove the `fields` list from the masking entry and keep only `fieldsNamePattern`","Or remove `fieldsNamePattern` and keep only the explicit `fields` list","Restart kafka-ui after correcting the config and confirm no validation error is logged"],"exampleFix":"// before\nmasking:\n  fields: [password, ssn]\n  fieldsNamePattern: \".*secret.*\"\n// after\nmasking:\n  fieldsNamePattern: \"(?i)(password|ssn|.*secret.*)\"","handlingStrategy":"validation","validationCode":"if (StringUtils.hasText(cfg.getFieldsNamePattern()) && !CollectionUtils.isEmpty(cfg.getFields())) {\n  throw new IllegalArgumentException(\"Provide either fields or fieldsNamePattern, not both\");\n}","typeGuard":"boolean isMaskingSelectorValid(ClustersProperties.Masking m) {\n  return StringUtils.hasText(m.getFieldsNamePattern()) ^ !CollectionUtils.isEmpty(m.getFields());\n}","tryCatchPattern":null,"preventionTips":["Keep each masking entry to exactly one selection mechanism","Add a config linter or startup test asserting the XOR condition","Document in your helm values/schema which of the two keys wins"],"tags":["configuration","validation","masking"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7","analyzedAt":"2026-09-08T04:35:39.002Z","contentChangedAt":"2026-09-08T04:35:39.002Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}