{"record":{"id":"e724eaf7a5c2ae9b","repo":"floci-io/floci","slug":"invalidifmatchversion","errorCode":"InvalidIfMatchVersion","errorMessage":"The If-Match version is missing or not valid for the resource.","messagePattern":"The If-Match version is missing or not valid for the resource\\.","errorType":"http","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontController.java","lineNumber":109,"sourceCode":"            String xml = new XmlBuilder()\n                    .start(\"DistributionConfig\", NS)\n                    .raw(xmlDistributionConfigBody(dist.getConfig()))\n                    .end(\"DistributionConfig\")\n                    .build();\n            return Response.ok(xml, XML).header(\"ETag\", dist.getEtag()).build();\n        } catch (AwsException e) {\n            return xmlErrorResponse(e);\n        }\n    }\n\n    @PUT\n    @Path(\"/distribution/{Id}/config\")\n    public Response updateDistribution(@PathParam(\"Id\") String id,\n                                       @HeaderParam(\"If-Match\") String ifMatch,\n                                       String body) {\n        try {\n            if (ifMatch == null || ifMatch.isEmpty()) {\n                throw new AwsException(\"InvalidIfMatchVersion\",\n                        \"The If-Match version is missing or not valid for the resource.\", 400);\n            }\n            DistributionConfig config = parseDistributionConfig(body);\n            Distribution updated = new Distribution();\n            updated.setConfig(config);\n            updated = service.updateDistribution(id, ifMatch, updated);\n            String xml = xmlDistribution(updated);\n            return Response.ok(xml, XML).header(\"ETag\", updated.getEtag()).build();\n        } catch (AwsException e) {\n            return xmlErrorResponse(e);\n        }\n    }\n\n    @DELETE\n    @Path(\"/distribution/{Id}\")\n    public Response deleteDistribution(@PathParam(\"Id\") String id,\n                                       @HeaderParam(\"If-Match\") String ifMatch) {\n        try {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontController.java#L91-L127","documentation":"InvalidIfMatchVersion from CloudFront's UpdateDistribution when the required If-Match header is missing or empty. CloudFront distribution updates are optimistic-concurrency controlled: the caller must echo the distribution's current ETag (obtained from GetDistribution/GetDistributionConfig) so the service can reject stale writes.","triggerScenarios":"PUT /distribution/{Id}/config without an If-Match header, or with an empty value — typically a hand-rolled HTTP client or an SDK call where the IfMatch field was never populated from a prior GET.","commonSituations":"Scripts that read the config, modify it, and PUT it back while forgetting to copy the ETag into If-Match; using the distribution Id in the header instead of the ETag; or holding an ETag long enough that an intermediate update changed it (which yields the same code).","solutions":["GET the distribution config first and copy its ETag response header into If-Match on the PUT.","With the AWS SDK, always set .ifMatch(etag) on the UpdateDistribution request using the ETag from the immediately preceding GetDistributionConfig.","If the error persists with a fresh ETag, another writer updated the distribution in between — re-GET, re-apply your change, and retry once."],"exampleFix":"// before\ncf.updateDistribution(req -> req.distributionId(id).distributionConfig(modified));\n\n// after\nvar current = cf.getDistributionConfig(req -> req.distributionId(id));\ncf.updateDistribution(req -> req.distributionId(id)\n        .ifMatch(current.eTag())\n        .distributionConfig(applyChanges(current.distributionConfig())));","handlingStrategy":"retry","validationCode":"String etag = cf.getDistributionConfig(req -> req.distributionId(id)).eTag();\nif (etag == null || etag.isBlank()) throw new IllegalStateException(\"No ETag; cannot update safely\");","typeGuard":null,"tryCatchPattern":"catch CloudFrontException code InvalidIfMatchVersion: re-GET the distribution config for a fresh ETag, re-apply your modifications to that fresh config, and retry the update once; a second consecutive failure means a concurrent writer — stop and investigate.","preventionTips":["Always GET-then-PUT: read config and ETag immediately before every update","Copy the ETag response header verbatim into If-Match (never the distribution Id)","Keep the GET→modify→PUT window short to avoid losing the race with other writers"],"tags":["cloudfront","etag","optimistic-concurrency","validation"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}