floci-io/floci · error · AwsException
PreconditionFailed
PreconditionFailed
Error message
The precondition in one or more request-header fields evaluated to false.
What it means
CloudFrontService.updatePublicKey throws PreconditionFailed (HTTP 412) when the If-Match header does not equal the key's current ETag. Public keys use ETag-based optimistic concurrency identical to the rest of CloudFront; each successful write rotates the UUID ETag and the next write must present the newest one.
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontService.java:950
"A public key with this caller reference already exists.",
409);
}
key.setId(UUID.randomUUID().toString());
key.setCreatedTime(Instant.now());
key.setEtag(UUID.randomUUID().toString());
publicKeyStore.put(key.getId(), key);
return key;
}
public PublicKey getPublicKey(String id) {
return publicKeyStore.get(id).orElseThrow(() ->
new AwsException("NoSuchPublicKey", "The specified public key does not exist.", 404));
}
public synchronized PublicKey updatePublicKey(String id, String ifMatch, PublicKey updated) {
PublicKey existing = getPublicKey(id);
if (!existing.getEtag().equals(ifMatch)) {
throw new AwsException(
"PreconditionFailed",
"The precondition in one or more request-header fields evaluated to false.",
412);
}
validatePublicKey(updated);
if (!Objects.equals(
existing.getCallerReference(),
updated.getCallerReference())
|| !Objects.equals(existing.getName(), updated.getName())
|| !Objects.equals(
existing.getEncodedKey(), updated.getEncodedKey())) {
throw new AwsException(
"CannotChangeImmutablePublicKeyFields",
"The caller reference, name, and encoded public key cannot be changed.",
400);
}
updated.setId(id);
updated.setCreatedTime(existing.getCreatedTime());View on GitHub (pinned to 62ff490619)
Solutions
- GetPublicKey immediately before updating and pass its ETag in If-Match.
- Carry the ETag returned by each UpdatePublicKey forward to the next mutation.
- Catch PreconditionFailed, refetch the ETag, and retry the update once.
Example fix
// before String etag = createResp.eTag(); updateKey(id, etag, v1); updateKey(id, etag, v2); // 412 // after var r1 = updateKey(id, createResp.eTag(), v1); var r2 = updateKey(id, r1.eTag(), v2);
Defensive patterns
Strategy: retry
Try / catch
for (int i = 0; i < 3; i++) {
String etag = client.getPublicKey(r -> r.id(id)).eTag();
try {
return client.updatePublicKey(r -> r.id(id).ifMatch(etag).publicKeyConfig(cfg));
} catch (PreconditionFailed e) {
// etag rotated; refetch and retry
}
} Prevention
- Use the ETag from the most recent Get/Update response.
- Update only the Comment field to minimize conflict windows.
- Keep a single writer per key id.
When it happens
Trigger: UpdatePublicKey with an ETag captured at creation when a prior update already rotated it; omitting If-Match; concurrent updates to the same key id where the loser's ETag is stale.
Common situations: Scripts that update a key's comment twice while caching the create-time ETag; stateful CLI sessions that hold old descriptions after background automation touched the key.
Related errors
- InvalidIfMatchVersion
- InvalidIfMatchVersion
- PublicKeyAlreadyExists
- CannotChangeImmutablePublicKeyFields
- PublicKeyInUse
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/3e243a0e2acda2db.
Report an issue: GitHub.