{"record":{"id":"53517bebb3938b77","repo":"apache/beam","slug":"expected-the-transform-service-config-to-contain-at-least","errorCode":null,"errorMessage":"Expected the Transform Service config to contain at least one Expansion Service.","messagePattern":"Expected the Transform Service config to contain at least one Expansion Service\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/transform-service/src/main/java/org/apache/beam/sdk/transformservice/TransformServiceConfig.java","lineNumber":57,"sourceCode":"\n    return new AutoValue_TransformServiceConfig(expansionservices);\n  }\n\n  static TransformServiceConfig parseFromYamlStream(InputStream inputStream) {\n    Yaml yaml = new Yaml();\n    Map<Object, Object> config = yaml.load(inputStream);\n    if (config == null) {\n      throw new IllegalArgumentException(\n          \"Could not parse the provided YAML stream into a non-trivial TransformServiceConfig\");\n    }\n\n    List<String> expansionservices = null;\n    if (config.get(\"expansionservices\") != null) {\n      expansionservices = (List<String>) config.get(\"expansionservices\");\n    }\n\n    if (expansionservices == null) {\n      throw new IllegalArgumentException(\n          \"Expected the Transform Service config to contain at least one Expansion Service.\");\n    }\n\n    return TransformServiceConfig.create(expansionservices);\n  }\n}\n","sourceCodeStart":39,"sourceCodeEnd":64,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/transform-service/src/main/java/org/apache/beam/sdk/transformservice/TransformServiceConfig.java#L39-L64","documentation":"Thrown by TransformServiceConfig.parseFromYamlStream when the YAML parsed into a map but has no 'expansionservices' key, so no expansion service endpoints were configured. The transform service needs at least one expansion service address to operate.","triggerScenarios":"Providing a YAML config mapping that lacks 'expansionservices' (or misspells it, e.g. 'expansionServices' — key lookup is exact and case-sensitive).","commonSituations":"Misspelled or camelCase key instead of the exact lowercase 'expansionservices'; copying a config from old docs; forgetting the key while adding other settings.","solutions":["Add an 'expansionservices' key with a list of endpoint addresses to the YAML.","Check the key spelling is exactly lowercase 'expansionservices' (not 'expansionServices').","Confirm the list is non-empty and each entry is a valid host:port address."],"exampleFix":"// before\nservices:\n  - \"localhost:12345\"\n// after\nexpansionservices:\n  - \"localhost:12345\"","handlingStrategy":"validation","validationCode":"@SuppressWarnings(\"unchecked\")\nstatic void validateConfigKeys(String path) throws IOException {\n  try (InputStream in = new FileInputStream(path)) {\n    Map<Object, Object> cfg = (Map<Object, Object>) new Yaml().load(in);\n    if (cfg == null || !cfg.containsKey(\"expansionservices\")) {\n      throw new IllegalArgumentException(path + \" must contain an 'expansionservices' list\");\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  config = TransformServiceConfig.parseFromYamlStream(stream);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"at least one Expansion Service\")) {\n    throw new IllegalArgumentException(\"Add 'expansionservices: [host:port, ...]' to the config YAML.\", e);\n  }\n  throw e;\n}","preventionTips":["Use the exact lowercase key 'expansionservices' — lookups are case-sensitive.","Keep a canonical example config in your repo and copy from it.","Add a unit test that parses every shipped config file."],"tags":["java","yaml","configuration","validation"],"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"}