{"record":{"id":"995f0d0a7e4d9d14","repo":"floci-io/floci","slug":"invaliddeploymentconfigexception","errorCode":"InvalidDeploymentConfigException","errorMessage":"ECS deployment group must specify ecsServices","messagePattern":"ECS deployment group must specify ecsServices","errorType":"exception","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/codedeploy/CodeDeployService.java","lineNumber":1214,"sourceCode":"        deployment.setStatus(\"Queued\");\n        deployment.setRevision(revision);\n        deployment.setCreateTime(now);\n        deployment.setDescription(description);\n        deployment.setCreator(\"user\");\n        deployment.setComputePlatform(\"ECS\");\n        deploymentsFor(region).put(deploymentId, deployment);\n\n        // Determine ECS cluster/service from deployment group\n        String clusterName = \"default\";\n        String serviceName = null;\n        List<Map<String, Object>> ecsSvcs = group.getEcsServices();\n        if (ecsSvcs != null && !ecsSvcs.isEmpty()) {\n            Map<String, Object> svc = ecsSvcs.get(0);\n            clusterName = (String) svc.getOrDefault(\"clusterName\", \"default\");\n            serviceName = (String) svc.get(\"serviceName\");\n        }\n        if (serviceName == null) {\n            throw new AwsException(\"InvalidDeploymentConfigException\",\n                    \"ECS deployment group must specify ecsServices\", 400);\n        }\n\n        // Determine blue/green TG ARNs from loadBalancerInfo\n        String blueTgArn = null;\n        String greenTgArn = null;\n        List<String> listenerArns = new ArrayList<>();\n        Map<String, Object> lbInfo = group.getLoadBalancerInfo();\n        if (lbInfo != null) {\n            List<Map<String, Object>> pairList = (List<Map<String, Object>>) lbInfo.get(\"targetGroupPairInfoList\");\n            if (pairList != null && !pairList.isEmpty()) {\n                Map<String, Object> pair = pairList.get(0);\n                List<Map<String, Object>> tgList = (List<Map<String, Object>>) pair.get(\"targetGroups\");\n                if (tgList != null && tgList.size() >= 2) {\n                    String blueName = (String) tgList.get(0).get(\"name\");\n                    String greenName = (String) tgList.get(1).get(\"name\");\n                    TargetGroup blueTg = elbV2Service.getTargetGroupByName(region, blueName);\n                    TargetGroup greenTg = elbV2Service.getTargetGroupByName(region, greenName);","sourceCodeStart":1196,"sourceCodeEnd":1232,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/codedeploy/CodeDeployService.java#L1196-L1232","documentation":"Thrown in createEcsDeployment (CodeDeployService.java:1214) when the deployment group's ecsServices list is null/empty or its first entry has no serviceName. The service reads clusterName (defaulting to 'default') and serviceName from group.getEcsServices().get(0); a null serviceName means the group cannot identify which ECS service to shift traffic for. Note the error code InvalidDeploymentConfigException is a questionable mapping — real AWS signals a malformed deployment group with ValidationException/InvalidDeploymentGroupException.","triggerScenarios":"CreateDeployment targeting a deployment group created with computePlatform=ECS but without serviceConfig/ecsServices (e.g., created with only tag filters), or with ecsServices[0] missing the serviceName key.","commonSituations":"Creating the deployment group with an older SDK shape ('ecsServices' vs newer nested serviceConfig); Terraform/CloudFormation group definitions missing the ecsServices block; testing against a group scaffolded as EC2 then repurposed for ECS.","solutions":["Recreate/update the deployment group with ecsServices: [{clusterName: '...', serviceName: '...'}].","Call GetDeploymentGroup first and verify ecsServices[0].serviceName is set before deploying.","Floci maintainers: align the error code with AWS (ValidationException or InvalidDeploymentGroupException)."],"exampleFix":"// before\nclient.create_deployment_group(applicationName='app', deploymentGroupName='ecs-dg',\n    computePlatform='ECS', serviceConfig=None)  # or omitted\n\n// after\nclient.create_deployment_group(applicationName='app', deploymentGroupName='ecs-dg',\n    computePlatform='ECS',\n    serviceConfig={'ecsServices': [{'clusterName': 'prod', 'serviceName': 'web'}]})","handlingStrategy":"validation","validationCode":"dg = client.get_deployment_group(applicationName=app,\n                                  deploymentGroupName=name)['deploymentGroupInfo']\nsvcs = dg.get('ecsServices') or []\nif not svcs or not svcs[0].get('serviceName'):\n    raise RuntimeError(f'deployment group {name} lacks ecsServices with serviceName')\nclient.create_deployment(applicationName=app, deploymentGroupName=name,\n                         revision=revision)","typeGuard":null,"tryCatchPattern":"try:\n    client.create_deployment(...)\nexcept client.exceptions.InvalidDeploymentConfigException as e:\n    if 'ecsServices' in str(e):\n        raise RuntimeError('fix the deployment group: add ecsServices[{clusterName, serviceName}]') from e\n    raise","preventionTips":["Create ECS deployment groups with serviceConfig.ecsServices always populated.","Validate the group with GetDeploymentGroup in a pre-deploy check step.","Never repurpose an EC2-tag-based group for ECS deployments."],"tags":["codedeploy","ecs","deployment-group","validation","emulator-parity"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}