Problem

When passing S3 artifacts to a AWS CodeBuild project through AWS CodePipeline, you might receive the error "Error calling startBuild: Source version should be empty for S3 folder source location" (CodeBuild, 400, InputValidationException). The error can be reproduced with the following CloudFormation definition:

  MyCodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: "MyCodeBuild"
      Artifacts:
        Type: S3
      # ...
      Source:
        Type: S3
        BuildSpec: buildspec.yaml
        Location: !Join ["", [!GetAtt [CodeBuildBucket, Arn], "/"]]

  # ...
  MyCodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: "MyCodePipeline"
      Stages:
      - Actions:
        - ActionTypeId:
            Category: Source
            Owner: "AWS"
            Provider: "S3"
            Version: "1"
          Name: PULL_CODEBUILD_SOURCES
          RunOrder: 1
          Configuration:
            PollForSourceChanges: false
            S3Bucket: !Ref CodeBuildBucket
            S3ObjectKey: "buildspec.yaml"
          OutputArtifacts:  
          - Name: CODEBUILD_SOURCES

The reason for the issue is, that MyCodeBuild does not declare any S3 object version for the primary source artifact. For a immutable file, this might be okay. But when having a dynamic input file with changing values, this is not a feasible way. A manual build of MyCodeBuild through the UI or CLI can be triggered without any problems. But as soon as the MyCodePipeline triggers the build after the buildspec.yaml has changed, CodePipeline automatically pass the object version of the buildspec.yaml to CodeBuild's inputArtifacts definition.

Solution

Using some sort of SourceVersion to MyCodeBuild does not work. You have to change the Source.Type from S3 to CODEBUILD. The drawback for this solution is, that you can no longer trigger the CodeBuild project manually:

  MyCodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: "MyCodeBuild"
      Artifacts:
        Type: CODEBUILD
      # ...
      Source:
        Type: CODEBUILD
        BuildSpec: buildspec.yaml
        Location: !Join ["", [!GetAtt [CodeBuildBucket, Arn], "/"]]