Troubleshooting CodePipeline Failures
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
Troubleshooting AWS CodePipeline Failures
Introduction: The Criticality of Pipeline Reliability
In modern software engineering, the delivery pipeline is the heartbeat of your application lifecycle. When your CI/CD pipeline—specifically AWS CodePipeline—is functioning correctly, code flows from a developer's local machine to production environments with minimal friction. However, when that pipeline fails, it creates a bottleneck that prevents critical features, bug fixes, and security patches from reaching your users. Understanding how to troubleshoot these failures is not just a secondary skill; it is a fundamental requirement for any engineer working in a cloud-native environment.
Troubleshooting CodePipeline is often intimidating because the service acts as an orchestrator rather than a single execution engine. A failure in CodePipeline is rarely a failure of CodePipeline itself; it is usually a symptom of an issue in one of the integrated services, such as AWS CodeBuild, CodeDeploy, S3, or IAM. This lesson will teach you how to decompose the complexity of these pipelines, isolate the root cause of failures, and implement structural changes to prevent future disruptions.
Understanding the Pipeline Architecture
To troubleshoot effectively, you must first visualize the pipeline as a series of distinct stages. Each stage consists of one or more actions. When a failure occurs, the pipeline stops execution at that specific action. Before diving into logs, you should identify exactly where the failure is occurring.
The Anatomy of a Pipeline Failure
Every pipeline action has an associated state. You can view these states in the AWS Management Console or via the AWS CLI. The primary states you will encounter during a failure are:
- Failed: The action did not complete successfully.
- Superseded: A newer execution has started, and this execution has been stopped.
- In Progress: The action is still executing.
When an action is in a "Failed" state, the console provides a link to the specific provider's logs. For example, if a CodeBuild action fails, the pipeline console provides a direct link to the CloudWatch Logs stream for that specific build. Understanding the relationship between these services is the first step in your investigation.
Callout: Orchestration vs. Execution It is important to distinguish between the orchestrator (CodePipeline) and the executor (CodeBuild, CodeDeploy, or custom Lambda functions). CodePipeline is responsible for moving artifacts and triggering stages, but it does not execute the build commands or deployment scripts itself. If your build script fails, it is an execution error, not an orchestration error.
Step-by-Step Troubleshooting Methodology
When you receive an alert that a pipeline has failed, do not jump straight into modifying code. Follow a structured approach to ensure you aren't chasing ghosts.
1. Identify the Failing Stage and Action
Navigate to the AWS CodePipeline console and select your pipeline. Locate the stage that is highlighted in red. Click on the action link within that stage. This will take you to the specific logs for the underlying service. If the action is a CodeBuild project, you will be taken to the "Build history" tab. If it is a CodeDeploy deployment, you will be taken to the "Deployment details" page.
2. Examine the Execution Logs
Once you are in the logs, look for the specific error message that caused the exit code of the process to be non-zero. In most build systems, a process exiting with a code other than 0 signifies an error.
- CodeBuild: Look at the
buildspec.ymlexecution logs in CloudWatch. Are there missing environment variables? Is a dependency failing to download? - CodeDeploy: Check the
codedeploy-agentlogs on the target instance or the deployment event logs in the console. Often, lifecycle hooks likeBeforeInstallorValidateServiceare the culprits. - S3/Artifact Issues: If the failure occurs between stages, it might be an issue with artifact encryption or bucket permissions. Check if the pipeline has the necessary KMS key access to decrypt the artifacts generated by the previous stage.
3. Reproduce the Failure Locally
If the error is related to a build script, try to run the script in your local environment or a Docker container that mimics the build environment. If the code builds locally but fails in the pipeline, the issue is almost certainly related to the environment configuration, such as missing IAM permissions, incorrect environment variables, or network restrictions.
Note: Always ensure your local environment is as close to the CI environment as possible. If your build runs on
Ubuntu 22.04in CodeBuild, don't test your scripts on a localmacOSmachine without using Docker to emulate the Linux environment.
Common Failure Scenarios and Solutions
Scenario A: IAM Permission Denied
A very common cause of failure is an IAM role that lacks the required permissions. For instance, if your CodeBuild project needs to push an image to an Amazon ECR repository, the service role attached to the CodeBuild project must have ecr:PutImage permissions.
How to troubleshoot:
- Check the build logs for
AccessDeniedor403 Forbiddenerrors. - Verify the IAM policy attached to the build project's service role.
- Ensure that the resource (like an S3 bucket or ECR repo) does not have a restrictive resource-based policy that denies access even if the IAM role has permissions.
Scenario B: Artifact Transformation Failures
CodePipeline uses S3 buckets to pass artifacts between stages. If the pipeline fails while moving from one stage to another, it is often due to an artifact naming mismatch or a failure to compress/decompress files.
How to troubleshoot:
- Check the
output-artifactsdefined in yourbuildspec.yml. - Ensure that the next stage is looking for the exact artifact name defined in the previous stage's output.
- Verify that the KMS key used for encrypting the artifact bucket is accessible by both the source and target roles.
Scenario C: Environment Variable Missing
Many pipelines rely on environment variables to inject configuration like API keys, database URLs, or feature flags. If these are missing, the build will fail immediately.
Code Example: Accessing Environment Variables in buildspec.yml
version: 0.2
phases:
install:
commands:
- echo "Installing dependencies..."
build:
commands:
- echo "Building the application..."
- if [ -z "$API_KEY" ]; then echo "API_KEY is missing!"; exit 1; fi
- ./build_script.sh
In this example, the script explicitly checks for the variable before proceeding. This is a best practice for debugging.
Best Practices for Resilient Pipelines
To minimize the time spent troubleshooting, you should design your pipelines with observability and failure recovery in mind.
1. Implement Detailed Logging
Don't rely on default logging levels. Configure your build scripts to output verbose logs when a failure occurs. In your buildspec.yml, use commands like set -x at the beginning of your scripts to print every command before it executes. This makes it significantly easier to see exactly where the script stopped.
2. Use Infrastructure as Code (IaC)
Never manually configure pipelines in the console. Use AWS CloudFormation, Terraform, or the AWS CDK to define your pipeline. When a pipeline fails due to a configuration error, you can easily compare your current code with previous versions to identify what changed.
3. Decouple Stages
Avoid creating "monolithic" stages that do too much. Break your pipeline into granular, logical steps:
- Source: Fetch code.
- Lint/Security Scan: Run static analysis.
- Build: Compile and package.
- Test: Run unit and integration tests.
- Deploy: Push to target environment.
By decoupling these, a failure in the "Test" stage doesn't require you to re-run the "Build" stage, saving time and reducing the surface area for errors.
Callout: The "Fail Fast" Philosophy A well-architected pipeline should fail as early as possible. If your unit tests are going to fail, you want them to fail immediately after the build, not after the deployment to a staging environment. Always place your most time-consuming and expensive tests after the quick sanity checks.
Comparison Table: Common Failure Origins
| Failure Symptom | Likely Origin | Troubleshooting Focus |
|---|---|---|
AccessDenied |
IAM / Resource Policy | Check Service Role permissions |
Command Not Found |
Build Environment | Review install phase in buildspec.yml |
Artifact Not Found |
S3 / Pipeline Config | Check artifact names and S3 paths |
Timeout |
Network / Resource | Check VPC settings and resource limits |
Deployment Failed |
CodeDeploy | Check appspec.yml and agent logs |
Advanced Troubleshooting: Network and VPC Issues
If your CodeBuild project is running inside a VPC to access private resources (like a private RDS instance or an internal API), you will encounter network-related failures that are harder to debug.
The VPC Trap
When a CodeBuild project is associated with a VPC, it loses default access to the public internet. If your build process needs to npm install packages from a public registry, it will fail unless you have configured a NAT Gateway or VPC Endpoints.
How to verify VPC connectivity:
- Check the "Network" settings in the CodeBuild project configuration.
- Ensure the subnets selected have a route to a NAT Gateway or an Internet Gateway.
- Verify that the Security Groups attached to the CodeBuild project allow outbound traffic on port 443 (HTTPS).
Tip: Use the curl command inside your buildspec.yml to test connectivity to your dependencies:
phases:
pre_build:
commands:
- echo "Testing connectivity..."
- curl -v https://registry.npmjs.org
If the curl command hangs or returns a connection timeout, you have a networking configuration issue rather than a code issue.
Managing Secrets and Configuration
One of the most frequent causes of pipeline failure is the mismanagement of secrets. Hardcoding credentials in your buildspec.yml is a security risk, but failing to inject them correctly is a common operational failure.
Using AWS Secrets Manager with CodeBuild
Instead of hardcoding secrets, use the secretsmanager parameter in your CodeBuild project configuration. This allows the build process to retrieve secrets at runtime without exposing them in plain text.
Example: Referencing a secret in buildspec.yml
env:
secrets-manager:
DB_PASSWORD: "my-app/db-password:password"
phases:
build:
commands:
- echo "Using database password..."
- ./connect_to_db.sh $DB_PASSWORD
If the build fails here, check the IAM role for the CodeBuild project to ensure it has secretsmanager:GetSecretValue permissions for the specified ARN.
Handling CodeDeploy Failures
CodeDeploy is often the final stage of a pipeline, and failures here are particularly stressful because they often involve production or staging environments. CodeDeploy failures usually stem from the appspec.yml file or the scripts it triggers.
Troubleshooting appspec.yml
The appspec.yml file dictates the deployment lifecycle. If a script fails during the ApplicationStart or ValidateService phase, the deployment will roll back.
Warning: By default, CodeDeploy rolls back if a deployment fails. While this is great for production stability, it wipes the logs on the target instance before you can inspect them. During development, you can disable automatic rollbacks to keep the instance in its "failed" state, allowing you to SSH in and inspect the files and logs manually.
Common CodeDeploy Pitfalls:
- Permissions: The
codedeploy-agentruns as therootuser, but the scripts it executes might be running as a different user. Ensure that permissions on your application files are set correctly. - Script Timeouts: If your deployment script takes longer than the default timeout (typically 3600 seconds), it will be killed. You can increase this in the
appspec.ymlor the deployment configuration. - Validation Failures: If you have a
ValidateServicehook, ensure it actually checks the health of the application. A common mistake is a validation script that returns0even when the application is not responding.
The Role of AWS CloudTrail in Troubleshooting
When all else fails, look at the audit trail. AWS CloudTrail records every API call made in your account. If your pipeline is failing due to an authorization issue or an unexpected state change, CloudTrail can show you exactly who (or what) initiated the change.
To use CloudTrail effectively:
- Filter by the service name (e.g.,
codepipeline.amazonaws.comorcodebuild.amazonaws.com). - Look for
ErrorCode: AccessDeniedorErrorCode: Client.UnauthorizedOperation. - Examine the
requestParametersto see the exact API call that failed.
This is particularly useful when dealing with cross-account pipelines, where permissions can become very complex. Seeing the actual API call will tell you exactly which account or role is being denied access.
Summary and Best Practices Checklist
To wrap up, let's consolidate the most important aspects of maintaining and troubleshooting a robust AWS CodePipeline.
The Troubleshooting Checklist
- Verify the Stage: Is the failure in the source, build, or deploy stage?
- Check the Logs: Are you looking at the correct CloudWatch log stream?
- Validate IAM: Does the service role have the necessary permissions for all involved resources?
- Check Networking: If the build is in a VPC, is there a NAT Gateway?
- Test Locally: Can the build command be executed successfully outside of the pipeline?
- Consult CloudTrail: Are there underlying API authorization issues?
- Review Secrets: Are secrets being fetched correctly from Secrets Manager or Parameter Store?
Key Takeaways for Your Team
- Observability is non-negotiable: If you cannot see it, you cannot fix it. Ensure all your scripts output meaningful, timestamped logs.
- Environment Parity: The closer your local development environment is to your pipeline environment, the fewer "it works on my machine" bugs you will encounter.
- Fail Fast, Fail Loud: Configure your pipelines to exit immediately upon failure and alert the relevant team members through SNS or Slack integrations.
- Use Infrastructure as Code: Manual changes are the enemy of consistency. If you change a pipeline setting, do it in your IaC template, not the console.
- Principle of Least Privilege: When troubleshooting, be careful not to "fix" an IAM issue by assigning
AdministratorAccess. Always grant the minimum permissions required for the task. - Document Recurring Failures: If you see the same pipeline failure more than once, it is no longer an "incident"—it is a design flaw. Update your build scripts or pipeline architecture to prevent it from happening again.
Common Questions (FAQ)
Q: My pipeline is stuck in "In Progress" for hours. What should I do? A: This usually indicates a hanging process or a resource lock. Check the build logs to see if a command is waiting for user input or if it is stuck in a loop. If the log is empty, check the underlying compute resource (e.g., the CodeBuild container or the CodeDeploy instance) to see if it has crashed.
Q: Can I manually restart a failed stage? A: Yes, you can click the "Retry" button in the CodePipeline console. However, if the underlying issue (like a bad configuration or a missing IAM permission) hasn't been fixed, the retry will simply fail again. Only retry after you have identified and addressed the root cause.
Q: Why does my pipeline say "Superseded"? A: This happens when you push a new commit to your source repository while the previous pipeline execution is still running. CodePipeline automatically stops the older, slower execution to prioritize the latest code. This is normal behavior and not an error.
Q: How do I handle multi-account pipelines? A: Multi-account pipelines require careful management of KMS keys and IAM roles. Ensure that the pipeline account has permission to assume roles in the target account, and that the target account's S3 buckets have policies allowing access from the pipeline account.
This comprehensive guide should serve as your primary reference for diagnosing and resolving issues within AWS CodePipeline. By following these structured methodologies and adhering to best practices, you can turn a failing pipeline from a source of frustration into a reliable, automated engine for your software delivery. Remember, the goal is not just to fix the error, but to understand the system well enough that the error does not recur.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons