floci-io/floci · error · AwsException

InvalidIfMatchVersion

InvalidIfMatchVersion

Error message

The If-Match version is missing or not valid for the resource.

What it means

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.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontController.java:109

            String xml = new XmlBuilder()
                    .start("DistributionConfig", NS)
                    .raw(xmlDistributionConfigBody(dist.getConfig()))
                    .end("DistributionConfig")
                    .build();
            return Response.ok(xml, XML).header("ETag", dist.getEtag()).build();
        } catch (AwsException e) {
            return xmlErrorResponse(e);
        }
    }

    @PUT
    @Path("/distribution/{Id}/config")
    public Response updateDistribution(@PathParam("Id") String id,
                                       @HeaderParam("If-Match") String ifMatch,
                                       String body) {
        try {
            if (ifMatch == null || ifMatch.isEmpty()) {
                throw new AwsException("InvalidIfMatchVersion",
                        "The If-Match version is missing or not valid for the resource.", 400);
            }
            DistributionConfig config = parseDistributionConfig(body);
            Distribution updated = new Distribution();
            updated.setConfig(config);
            updated = service.updateDistribution(id, ifMatch, updated);
            String xml = xmlDistribution(updated);
            return Response.ok(xml, XML).header("ETag", updated.getEtag()).build();
        } catch (AwsException e) {
            return xmlErrorResponse(e);
        }
    }

    @DELETE
    @Path("/distribution/{Id}")
    public Response deleteDistribution(@PathParam("Id") String id,
                                       @HeaderParam("If-Match") String ifMatch) {
        try {

View on GitHub (pinned to 62ff490619)

Solutions

  1. GET the distribution config first and copy its ETag response header into If-Match on the PUT.
  2. With the AWS SDK, always set .ifMatch(etag) on the UpdateDistribution request using the ETag from the immediately preceding GetDistributionConfig.
  3. If the error persists with a fresh ETag, another writer updated the distribution in between — re-GET, re-apply your change, and retry once.

Example fix

// before
cf.updateDistribution(req -> req.distributionId(id).distributionConfig(modified));

// after
var current = cf.getDistributionConfig(req -> req.distributionId(id));
cf.updateDistribution(req -> req.distributionId(id)
        .ifMatch(current.eTag())
        .distributionConfig(applyChanges(current.distributionConfig())));
Defensive patterns

Strategy: retry

Validate before calling

String etag = cf.getDistributionConfig(req -> req.distributionId(id)).eTag();
if (etag == null || etag.isBlank()) throw new IllegalStateException("No ETag; cannot update safely");

Try / catch

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.

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/e724eaf7a5c2ae9b. Report an issue: GitHub.