terraform-provider-aws: aws_cloudfront_function PreconditionFailed: The request failed because it didn't meet the preconditions in one or more request-header fields.

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave “+1” or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform CLI and Terraform AWS Provider Version

Terraform v0.13.5 Provider v3.42.0

Affected Resource(s)

  • aws_cloudfront_function

Terraform Configuration Files

Please include all Terraform configurations required to reproduce the bug. Bug reports without a functional reproduction may be closed without investigation.

resource "aws_cloudfront_function" "cloudfront_security_headers" {
  name    = "MyFunction"
  runtime = "cloudfront-js-1.0"
  publish = true
  code    = file("${path.module}/../../src/index.js")
}

Debug Output

https://gist.github.com/hougholi/0f099da4f04599fbe26e38e0568b1f45

Expected Behavior

CloudFront function code should be updated.

Actual Behavior

Error: error updating CloudFront Function (dev-cloudfront-security-headers) configuration : PreconditionFailed: The request failed because it didn’t meet the preconditions in one or more request-header fields. status code: 412, request id: 38cb6e1b-b74a-4f1c-bb91-0c385e39c88d

Steps to Reproduce

Update CloudFront function code and run terraform apply.

Important Factoids

The function already exists in AWS, this error only occurs when updating the code and trying to run terraform apply

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 50
  • Comments: 20 (5 by maintainers)

Most upvoted comments

From: https://www.terraform.io/docs/cli/commands/refresh.html

You shouldn’t typically need to use this command, because Terraform automatically performs the same refreshing actions as a part of creating a plan in both the terraform plan and terraform apply commands. This command is here primarily for backward compatibility, but we don’t recommend using it because it provides no opportunity to review the effects of the operation before updating the state.

Performing a plan/apply will refresh your state. The problem here is that with publish=true the etag retrieved is for the published (LIVE) version of the cloudfront function. If for some reason the etag of the published version and the unpublished (DEVELOPMENT) version does not match, the request to update the published function fails. I’ve fixed this in #19697 and I’ve been using a local version of the provider in production since I opened the PR in our production environment with no issues.

A separate issue that causes a similar precondition errors happens if a plan will modify both the distribution & cloudfront function that is published. The cloudfront function being published actually modifies the etag of the distribution. Which is where @alexjurkiewicz first proposal would be useful as it would help alleviate inter-resource etag conflicts. You can see this already being done for cloudfront distribution deletions https://github.com/hashicorp/terraform-provider-aws/blob/bae3b38b6508172254ff696e8ba1126cf8c55ee8/aws/resource_aws_cloudfront_distribution.go#L1015-L1036

I am interested in fixing this issue, it causes problems for us. I can see a few ways forward:

  1. When modifying a function, if there is a failure due to etag mismatch, silently pull the latest etag and retry
  2. Require the user to run terraform refresh to update the etag

If a maintainer could confirm the preferred approach, I will code it up.

This error is returned because the ETag value in state isn’t equal to the current value at AWS (because the function was updated outside Terraform):

https://github.com/hashicorp/terraform-provider-aws/blob/da4fb15cfa46e41bdcf4b596a3721f040d98511e/aws/resource_aws_cloudfront_function.go#L159-L182

I now have this issue with a function in production - so I can’t delete it and let Terraform recreate. So yeah it’s worth fixing.

Same here. I would expect it to work again after running terraform refresh but the same precondition error occurs.

It appears that there’s a bug with etag value for the LIVE & DEVELOPMENT stages of the function and having publish = true. Each stage has separate etag value and when the function is refreshed with publish = true the etag stored is the value of the LIVE function. I can see in the state of a cloudfront function not manually modified (but one that has been updated via terraform) the etag matches the function inDEVELOPMENT stage. In fact the etag of LIVE & DEVELOPMENT stages match.

Running for the same exception. I am fixing it by running with publish=false then after applied the code, run it back with publish=true it seems tf is getting lost dealing with trying publish it before saves the code.

Error: error updating CloudFront Distribution

Your failure is when updating the cloudfront distribution, not the cloudfront function. Theres a separate issue I described in this comment https://github.com/hashicorp/terraform-provider-aws/issues/19529#issuecomment-877125478. I’ll create a bug report on it.

I now have this issue with a function in production - so I can’t delete it and let Terraform recreate. So yeah it’s worth fixing.

Another workaround is to remove it from the state file (terraform state rm) and add it back in (terraform import) before updating.

Thanks for reopening 👍 - yes I did the same, but it is still worth fixing I think - ideally manual changes would be detected and reset by terraform - they are ignored at the moment, I guess that’s a separate issue though