How to fix Pipeline failed: Job 'test' failed in Git

GitBEGINNERMEDIUMUpdated Dec 6, 2025· 244 views

This GitLab CI/CD error occurs when one or more jobs in your pipeline fail. The failure can be caused by test failures, script errors, configuration issues, or external dependencies. To fix it, examine the job logs, identify the root cause, and resolve the underlying issue.

Quick fix

Fixes Pipeline failed: Job 'test' failed

# Example job log showing a test failure:
$ npm test
FAIL  src/utils.test.js
  ✕ should return correct sum (5 ms)

  ● should return correct sum
    expect(received).toBe(expected)
    Expected: 5
    Received: 4

Test Suites: 1 failed, 1 total
ERROR: Job failed: exit code 1
  1. View the failed job logs
  2. Reproduce the failure locally
  3. Fix test failures
  4. Fix build or compilation errors
git — error
# Example job log showing a test failure:
$ npm test
FAIL src/utils.test.js
✕ should return correct sum (5 ms)
● should return correct sum
expect(received).toBe(expected)
Expected: 5
Received: 4
Test Suites: 1 failed, 1 total
ERROR: Job failed: exit code 1
Pipeline failed: Job 'test' failed

What this error means

When you see "Pipeline failed: Job 'test' failed" (or any similar job name), GitLab is telling you that one of the jobs defined in your CI/CD pipeline did not complete successfully. A job fails when its script returns a non-zero exit code. GitLab CI/CD pipelines consist of stages, and each stage can have multiple jobs. When a job fails, it typically prevents downstream jobs and stages from running (unless configured otherwise with `allow_failure`). The pipeline as a whole is marked as failed. This is GitLab's way of protecting your codebase from broken code being deployed or merged. The failed job indicates that something went wrong - it could be failing tests, a build error, a linting violation, a deployment issue, or even a misconfigured CI script. Understanding why the job failed requires examining the job logs, which show the exact command that failed and any error output. The job name in the error message (like 'test', 'build', 'lint', or 'deploy') gives you a hint about what type of failure occurred.

Typical symptoms

  • GitLab shows 'Pipeline #XXXX failed' with red status icon
  • Merge request shows 'Pipeline failed' and merge is blocked
  • Job shows red X with 'failed' status in pipeline view
  • Email notification: 'Pipeline for your-branch has failed'
  • Commit status badge shows red/failed state
  • Auto-merge is blocked waiting for pipeline
  • GitLab shows 'Job failed: exit code 1' or similar in job log
  • Downstream jobs show 'skipped' because upstream job failed
  • Merge train removed your MR due to pipeline failure

Common causes

  1. Test suite failures - unit tests, integration tests, or end-to-end tests not passing
  2. Build compilation errors - code doesn't compile or build successfully
  3. Linting or code style violations - ESLint, Prettier, Black, or other linters finding issues
  4. Script syntax errors in .gitlab-ci.yml - invalid YAML or incorrect commands
  5. Missing dependencies - packages not installed or unavailable
  6. Environment variable not set or configured incorrectly
  7. Docker image not found or pull failed
  8. External service unavailable - API, database, or registry timeout
  9. Timeout - job exceeded configured or default time limit
  10. Runner resource exhaustion - out of memory or disk space
  11. Permission denied errors - accessing files or services without proper access
  12. Network connectivity issues - unable to reach external resources
  13. Invalid artifact or cache - corrupted or missing build artifacts
  14. Security scanner findings - SAST, DAST, or dependency scanning failures

How to fix "Pipeline failed: Job 'test' failed"

1View the failed job logs

First, identify what caused the job to fail by examining the logs:

1. Navigate to your project in GitLab
2. Click on Build > Pipelines in the sidebar
3. Find the failed pipeline and click on it
4. Click on the failed job (marked with red X)
5. Review the job log output

text
# Example job log showing a test failure:
$ npm test
FAIL  src/utils.test.js
  ✕ should return correct sum (5 ms)

  ● should return correct sum
    expect(received).toBe(expected)
    Expected: 5
    Received: 4

Test Suites: 1 failed, 1 total
ERROR: Job failed: exit code 1

The key information is usually near the end of the log, right before "Job failed". Look for error messages, stack traces, or assertion failures.

2Reproduce the failure locally

Before making changes, reproduce the issue on your machine:

bash
# Pull the latest code
git fetch origin
git checkout your-branch

# Run the same command that failed in CI
# For test failures:
npm test
# or
pytest
# or
go test ./...
# or
mvn test

# For build failures:
npm run build
# or
make build

# For lint failures:
npm run lint
# or
eslint .

Tip: If the failure only happens in CI, check for environment differences:
- Different Node/Python/Go version
- Missing environment variables
- Cached dependencies vs fresh install
- Different OS (GitLab runner vs local machine)

To match CI environment more closely:

bash
# Clear caches and reinstall
rm -rf node_modules package-lock.json
npm install
npm test
3Fix test failures

If the job failed due to failing tests, fix the tests or the code:

Common test failure scenarios:

1. Assertion failure - Update the test or fix the code:

javascript
// Fix the actual code
function add(a, b) {
  return a + b; // was: return a - b;
}

2. Snapshot mismatch - Update snapshots if changes are intentional:

bash
npm test -- --updateSnapshot
# or
jest --updateSnapshot

3. Async test timeout - Increase timeout or fix async handling:

javascript
test('async operation', async () => {
  jest.setTimeout(10000); // Increase timeout
  const result = await slowOperation();
  expect(result).toBeDefined();
}, 10000);

4. Environment-dependent test - Mock external dependencies:

javascript
// Mock API calls that may fail in CI
jest.mock('./api', () => ({
  fetchData: jest.fn().mockResolvedValue({ data: 'test' })
}));

After fixing, push your changes:

bash
git add .
git commit -m "fix: resolve failing tests"
git push origin your-branch
4Fix build or compilation errors

For build failures, address the compilation or bundling issues:

TypeScript/JavaScript build errors:

bash
# Check for TypeScript errors
npx tsc --noEmit

# Common fixes:
# - Add missing type definitions
# - Fix type mismatches
# - Install missing @types packages
npm install --save-dev @types/node

Import/export issues:

typescript
// Wrong - named vs default export mismatch
import MyComponent from './MyComponent'; // expects default export
export const MyComponent = () => {}; // but this is named export

// Fix:
export default MyComponent;
// or
import { MyComponent } from './MyComponent';

Missing dependencies:

bash
# Install missing packages
npm install missing-package

# For monorepos, ensure you're in the right directory
cd packages/my-app
npm install

Docker build failures:

dockerfile
# Ensure base image exists
FROM node:18-alpine  # Use specific version

# Copy package files before code for better caching
COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build
5Fix configuration and script errors

Check your .gitlab-ci.yml for configuration issues:

Validate your CI configuration:
1. Go to Build > Pipeline editor in GitLab
2. Paste your .gitlab-ci.yml content
3. Click Validate to check for syntax errors

Common configuration mistakes:

1. Using tabs instead of spaces:

yaml
# Wrong - YAML requires spaces, not tabs
test:
	script: npm test  # Tab character!

# Correct:
test:
  script: npm test

2. Missing script keyword:

yaml
# Wrong:
test:
  - npm test

# Correct:
test:
  script:
    - npm test

3. Invalid before_script usage:

yaml
# Correct structure:
test:
  before_script:
    - npm ci
  script:
    - npm test

4. Stage not defined:

yaml
# Must define stages used by jobs
stages:
  - test
  - build
  - deploy

test-job:
  stage: test  # Must be in stages list
  script:
    - npm test
6Handle environment and dependency issues

Fix problems related to environment variables and dependencies:

Missing environment variables:

yaml
# Define variables in .gitlab-ci.yml
variables:
  NODE_ENV: "test"
  DATABASE_URL: $CI_DATABASE_URL  # Use CI/CD variables

test:
  script:
    - npm test

Set sensitive variables in GitLab:
1. Go to Settings > CI/CD > Variables
2. Add your variable (e.g., API_KEY)
3. Mark as "Masked" for sensitive values

Dependency installation failures:

yaml
# Use npm ci for clean installs in CI
install:
  script:
    - npm ci  # Not 'npm install'

# Or with caching:
test:
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
  script:
    - npm ci
    - npm test

Docker image issues:

yaml
# Specify exact image version
test:
  image: node:18.17.0-alpine
  script:
    - npm ci
    - npm test

# For custom registries, authenticate first
before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
7Retry the job for transient failures

If the failure appears to be transient (network timeout, flaky test), retry the job:

Manual retry:
1. Navigate to the failed job
2. Click Retry button in the top-right corner

Configure automatic retry in .gitlab-ci.yml:

yaml
test:
  script:
    - npm test
  retry:
    max: 2
    when:
      - runner_system_failure
      - stuck_or_timeout_failure
      - script_failure  # For flaky tests

# Different retry for different failure types:
deploy:
  script:
    - ./deploy.sh
  retry:
    max: 1
    when:
      - runner_system_failure
      - stuck_or_timeout_failure
      # Don't retry script failures for deployment

Retry entire pipeline:
- Push an empty commit to trigger a new pipeline:

bash
git commit --allow-empty -m "ci: retry pipeline"
git push origin your-branch

Or use GitLab quick actions in MR comments:

text
/rebase
8Handle timeout issues

If your job is timing out, extend the timeout or optimize the job:

Increase job timeout:

yaml
test:
  script:
    - npm test
  timeout: 30 minutes  # Default is usually 1 hour

# For very long jobs:
e2e_tests:
  script:
    - npm run test:e2e
  timeout: 2 hours

Optimize job execution:

yaml
# Run tests in parallel
test:
  parallel: 4
  script:
    - npm test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL

# Use caching effectively
test:
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
      - .npm/
  script:
    - npm ci --cache .npm
    - npm test

# Split into multiple jobs
test_unit:
  stage: test
  script:
    - npm run test:unit

test_integration:
  stage: test
  script:
    - npm run test:integration

Check runner resources:
- Request larger runner if available
- Check if shared runners are overloaded
- Consider using your own runners for resource-intensive jobs

9Allow job failure when appropriate

For non-critical jobs, configure them to not block the pipeline:

yaml
# Job can fail without failing the pipeline
optional_lint:
  script:
    - npm run lint:experimental
  allow_failure: true

# Allow failure only for specific exit codes
test_new_feature:
  script:
    - npm test -- --experimental
  allow_failure:
    exit_codes:
      - 1
      - 137  # OOM killed

# Allow failure only on specific branches
staging_deploy:
  script:
    - ./deploy.sh staging
  allow_failure: true
  rules:
    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH

Use this sparingly - only for truly optional jobs like:
- Experimental feature tests
- Non-blocking code quality checks
- Optional security scans
- Performance benchmarks

Warning: Don't use allow_failure to hide real problems!

Advanced notes

### Understanding Job Exit Codes

Common exit codes and their meanings:

| Exit Code | Meaning | Common Cause |
|-----------|---------|--------------|
| 1 | General error | Test failure, script error |
| 2 | Misuse of command | Invalid arguments |
| 126 | Permission denied | Script not executable |
| 127 | Command not found | Missing binary/tool |
| 128 | Invalid exit argument | Script returned invalid code |
| 137 | SIGKILL (128+9) | Out of memory, killed by system |
| 139 | SIGSEGV (128+11) | Segmentation fault |
| 143 | SIGTERM (128+15) | Job timeout, terminated |

### Debugging with Artifacts

Preserve logs and artifacts from failed jobs:

yaml
test:
  script:
    - npm test
  artifacts:
    when: on_failure  # Only upload on failure
    paths:
      - test-results/
      - coverage/
      - logs/
    expire_in: 1 week

### Using rules vs only/except

Modern GitLab CI uses rules instead of only/except:

yaml
# Modern approach with rules:
test:
  script:
    - npm test
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

# Avoid deprecated only/except syntax:
# only:
#   - merge_requests
#   - main

### Needs and Dependencies

Control job execution order with needs:

yaml
stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  needs: ["build"]  # Wait only for build, not all of previous stage
  script:
    - npm test

deploy:
  stage: deploy
  needs: ["build", "test"]
  script:
    - ./deploy.sh

### Using Services for Integration Tests

For tests requiring databases or other services:

yaml
test:
  image: node:18
  services:
    - postgres:15
    - redis:7
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: test
    POSTGRES_PASSWORD: test
    DATABASE_URL: "postgresql://test:test@postgres:5432/test_db"
    REDIS_URL: "redis://redis:6379"
  script:
    - npm ci
    - npm run db:migrate
    - npm test

### Interruptible Jobs

Stop redundant pipelines when new commits are pushed:

yaml
workflow:
  auto_cancel:
    on_new_commit: interruptible

test:
  interruptible: true
  script:
    - npm test

deploy:
  interruptible: false  # Never cancel deployments
  script:
    - ./deploy.sh

### Troubleshooting Runner Issues

If jobs fail due to runner problems:

yaml
# Request specific runner tags
test:
  tags:
    - docker
    - linux
  script:
    - npm test

# Check runner configuration
variables:
  # For Docker-in-Docker
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"

Contact your GitLab administrator if shared runners consistently fail.

Frequently asked questions

What does "Pipeline failed: Job 'test' failed" mean?
When you see "Pipeline failed: Job 'test' failed" (or any similar job name), GitLab is telling you that one of the jobs defined in your CI/CD pipeline did not complete successfully. A job fails when its script returns a non-zero exit code. GitLab CI/CD pipelines consist of stages, and each stage can have multiple jobs.
How do I fix "Pipeline failed: Job 'test' failed"?
This GitLab CI/CD error occurs when one or more jobs in your pipeline fail. The failure can be caused by test failures, script errors, configuration issues, or external dependencies. To fix it, examine the job logs, identify the root cause, and resolve the underlying issue.
What causes "Pipeline failed: Job 'test' failed"?
Test suite failures - unit tests, integration tests, or end-to-end tests not passing Build compilation errors - code doesn't compile or build successfully Linting or code style violations - ESLint, Prettier, Black, or other linters finding issues
Is the "Pipeline failed: Job 'test' failed" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading