{"record":{"id":"997768052c5b0969","repo":"apache/beam","slug":"expected-each-entry-in-the-allowlist-to-include-the","errorCode":null,"errorMessage":"Expected each entry in the allowlist to include the 'className'","messagePattern":"Expected each entry in the allowlist to include the 'className'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java","lineNumber":511,"sourceCode":"      Yaml yaml = new Yaml();\n      Map<Object, Object> config = yaml.load(inputStream);\n\n      if (config == null) {\n        throw new IllegalArgumentException(\n            \"Could not parse the provided YAML stream into a non-trivial AllowList\");\n      }\n\n      String version = config.get(\"version\") != null ? (String) config.get(\"version\") : \"\";\n      List<AllowedClass> allowedClasses = new ArrayList<>();\n      if (config.get(\"allowedClasses\") != null) {\n        allowedClasses =\n            ((List<Map<Object, Object>>) config.get(\"allowedClasses\"))\n                .stream()\n                    .map(\n                        data -> {\n                          String className = (String) data.get(\"className\");\n                          if (className == null) {\n                            throw new IllegalArgumentException(\n                                \"Expected each entry in the allowlist to include the 'className'\");\n                          }\n                          List<String> allowedBuilderMethods =\n                              (List<String>) data.get(\"allowedBuilderMethods\");\n                          List<String> allowedConstructorMethods =\n                              (List<String>) data.get(\"allowedConstructorMethods\");\n                          if (allowedBuilderMethods == null) {\n                            allowedBuilderMethods = new ArrayList<>();\n                          }\n                          if (allowedConstructorMethods == null) {\n                            allowedConstructorMethods = new ArrayList<>();\n                          }\n                          return AllowedClass.create(\n                              className, allowedBuilderMethods, allowedConstructorMethods);\n                        })\n                    .collect(Collectors.toList());\n      }\n      return AllowList.create(version, allowedClasses);","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java#L493-L529","documentation":"parseFromYamlStream walks each entry under allowedClasses in the allowlist YAML and found an entry lacking the mandatory 'className' key. The allowlist YAML stream is the faulty input: every allowedClasses item must carry className (plus optional builder/constructor method filters) to identify the class being allowed.","triggerScenarios":"Parsing an allowlist YAML where an allowedClasses list element omits 'className', misspells it ('classname', 'class_name'), or its value is not a String.","commonSituations":"Hand-edited allowlist files, copy-pasted examples with renamed fields, YAML anchor merges dropping the key.","solutions":["Add a 'className' string to every entry under allowedClasses.","Check key casing: it must be exactly 'className'.","Diff your allowlist against a known-good example from Beam docs."],"exampleFix":"# before\nallowedClasses:\n  - classname: org.example.MyTransform\n# after\nallowedClasses:\n  - className: org.example.MyTransform","handlingStrategy":"validation","validationCode":"Map<Object,Object> cfg = new Yaml().load(stream);\nList<?> entries = (List<?>) cfg.get(\"allowedClasses\");\nfor (Object e : entries) {\n  if (!(e instanceof Map) || ((Map<?,?>) e).get(\"className\") == null)\n    throw new IllegalArgumentException(\"allowedClasses entry missing 'className'\");\n}","typeGuard":"boolean entryHasClassName(Map<Object,Object> entry) { return entry.get(\"className\") instanceof String && !((String) entry.get(\"className\")).isEmpty(); }","tryCatchPattern":"try { AllowList list = AllowList.parseFromYamlStream(stream); } catch (IllegalArgumentException e) { log.error(\"Malformed allowlist entry: {}\", e.getMessage()); throw new InvalidConfigException(e); }","preventionTips":["Always include className first in every entry","Lint allowlist YAML with a schema in CI","Avoid renaming fields when copying examples","Use YAML anchors carefully so merges do not drop className"],"tags":["yaml","configuration","schema"],"backgroundTag":"missing-required-config-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}