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
- 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.
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
- 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
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
- InvalidIfMatchVersion
- PreconditionFailed
- InvalidArgument
- CannotChangeImmutablePublicKeyFields
- TLS enabled but no certificate provided and self-signed gene
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/e724eaf7a5c2ae9b.
Report an issue: GitHub.