{"record":{"id":"ed920242c0ff8542","repo":"floci-io/floci","slug":"invalidrevisionexception","errorCode":"InvalidRevisionException","errorMessage":"Revision is required","messagePattern":"Revision is required","errorType":"exception","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/codedeploy/CodeDeployService.java","lineNumber":965,"sourceCode":"                }\n\n                if (!\"Success\".equals(invocationStatus) && !\"InProgress\".equals(invocationStatus)) {\n                    finishLifecycleEvent(event, \"Failed\");\n                    return false;\n                }\n            } catch (Exception e) {\n                LOG.debugv(\"SSM execution failed for {0} on {1}: {2}\", location, instanceId, e.getMessage());\n                // Graceful degradation: if SSM fails, treat as succeeded\n            }\n        }\n        finishLifecycleEvent(event, \"Succeeded\");\n        return true;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private ServerAppSpecInfo parseServerAppSpec(Map<String, Object> revision) {\n        if (revision == null) {\n            throw new AwsException(\"InvalidRevisionException\", \"Revision is required\", 400);\n        }\n\n        String content = null;\n        Object appSpecContent = revision.get(\"appSpecContent\");\n        if (appSpecContent instanceof Map<?, ?> asc) {\n            content = (String) ((Map<String, Object>) asc).get(\"content\");\n        }\n\n        ServerAppSpecInfo info = new ServerAppSpecInfo();\n        info.os = \"linux\";\n        info.hooks = new java.util.LinkedHashMap<>();\n\n        if (content == null || content.isBlank()) {\n            return info;\n        }\n\n        try {\n            JsonNode root = yamlMapper.readTree(content);","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/codedeploy/CodeDeployService.java#L947-L983","documentation":"Thrown by parseServerAppSpec (CodeDeployService.java:965) when createServerDeployment receives a null revision. For EC2/on-premises compute platforms the appSpec (and its revision container) is mandatory — unlike Lambda deployments, CodeDeploy cannot infer an application revision, so the emulator rejects the call with InvalidRevisionException before any deployment record is created.","triggerScenarios":"CreateDeployment with computePlatform=Server (EC2/on-premises) and no revision member in the request; passing a request where the revision key was serialized under a different name or dropped by a client-side struct.","commonSituations":"Copy-pasting a Lambda deployment script (where revision may be optional) for a server deployment; SDK request objects where revision is left None; JSON built by hand with a typo like 'Revision' or 'revison'.","solutions":["Supply revision.appSpecContent.content with a valid AppSpec file for every server deployment.","If you meant to deploy without a revision, switch computePlatform to Lambda where a revision from the deployment group may apply.","Log/inspect the serialized request body right before the call to confirm the revision key is present at the top level."],"exampleFix":"// before\nclient.create_deployment(\n    applicationName='my-app',\n    deploymentGroupName='my-dg',\n    # revision missing\n)\n\n// after\nclient.create_deployment(\n    applicationName='my-app',\n    deploymentGroupName='my-dg',\n    revision={\n        'appSpecContent': {'content': 'version: 0.0\\nResources: []\\nHooks: []'}\n    },\n)","handlingStrategy":"validation","validationCode":"def build_server_revision(appspec_text: str) -> dict:\n    if not appspec_text or not appspec_text.strip():\n        raise ValueError('server AppSpec content is required')\n    return {'appSpecContent': {'content': appspec_text}}\n\nclient.create_deployment(\n    applicationName=app, deploymentGroupName=dg,\n    computePlatform='Server',\n    revision=build_server_revision(appspec_text))","typeGuard":"def has_valid_revision(request: dict) -> bool:\n    rev = request.get('revision')\n    return isinstance(rev, dict) and isinstance(rev.get('appSpecContent'), dict)","tryCatchPattern":"try:\n    client.create_deployment(...)\nexcept client.exceptions.InvalidRevisionException as e:\n    if 'Revision is required' in str(e):\n        raise RuntimeError('server deployments require revision.appSpecContent') from e\n    raise","preventionTips":["Centralize revision construction in one builder function per compute platform.","Add a unit test asserting every deploy path emits a non-null revision.","Never reuse a Lambda deploy script verbatim for server groups."],"tags":["codedeploy","server-deployment","appspec","revision","validation"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}