# Drone Build Error: Complete Troubleshooting Guide
Drone CI is a container-native CI/CD platform that runs pipelines in Docker containers. When builds fail, it's usually related to Docker execution, pipeline configuration, or secret management.
Let me walk through the most common Drone build errors and how to fix each one systematically.
Understanding Drone Pipeline Logs
Drone logs are straightforward but can be sparse:
- 1.Go to your repository in Drone
- 2.Click on the failed build number
- 3.Click on the failed step to expand logs
- 4.Look for
exit code 1or error messages
Drone uses a simple YAML format that's different from other CI systems. Understanding the structure helps debug issues.
Fix 1: Pipeline YAML Syntax Errors
Drone YAML has specific requirements.
Symptoms: - Build doesn't start - "YAML parsing error" - Pipeline ignored completely
Common YAML issues:
```yaml # WRONG - missing kind/type at top pipeline: build: image: node:20 commands: - npm install
# CORRECT - specify pipeline type kind: pipeline type: docker name: default
steps: - name: build image: node:20 commands: - npm install ```
Other syntax problems:
```yaml # WRONG - old format (Drone 0.8) pipeline: build: image: node:20
# CORRECT - new format (Drone 1.0+) kind: pipeline type: docker name: default
steps: - name: build image: node:20 ```
Solution:
Validate YAML syntax:
```yaml kind: pipeline type: docker name: default
steps: - name: install image: node:20 commands: - npm ci
- name: test
- image: node:20
- commands:
- - npm test
- name: build
- image: node:20
- commands:
- - npm run build
`
Fix 2: Docker Image Pull Failures
Images can't be pulled or don't exist.
Symptoms: - "Error: image pull failed" - "Error: manifest unknown" - Long delay before build starts
Solution A: Use public images correctly:
steps:
- name: build
image: node:20.11.0-alpine # Specify exact tag
commands:
- npm ciSolution B: Use private images:
steps:
- name: build
image: registry.company.com/my-image:latest
pull: always # Always pull latest
commands:
- ./build.shFor private registries, configure pull secrets:
```yaml kind: secret name: docker_password get: path: secrets/docker name: password
kind: pipeline type: docker name: default
steps: - name: build image: registry.company.com/my-image:latest pull_secrets: - docker_config ```
Or in Drone server config:
# Configure Docker registry in Drone server
DRONE_DOCKER_CONFIG=/path/to/docker/config.jsonSolution C: Use local images:
steps:
- name: build
image: my-local-image
pull: if-not-exists # Only pull if not present locallyFix 3: Container Execution Errors
Commands fail inside containers.
Symptoms:
- command not found
- Permission denied
- Exit code 127
Solution A: Choose correct base image:
```yaml # For Node.js - name: build image: node:20 commands: - npm --version # npm is available
# For Python - name: test image: python:3.11 commands: - pip install pytest - pytest
# For Go - name: build image: golang:1.21 commands: - go build ```
Solution B: Install missing tools:
- name: build
image: node:20
commands:
- apt-get update && apt-get install -y jq curl
- npm ciSolution C: Fix permissions:
- name: build
image: node:20
commands:
- chmod +x ./scripts/*.sh
- ./scripts/build.shImportant: Drone runs commands in /drone/src as a non-root user by default.
Fix 4: Environment Variable Issues
Variables not available or incorrectly formatted.
Symptoms: - Empty values in variables - Wrong syntax used
Solution A: Use correct variable syntax:
steps:
- name: build
image: node:20
environment:
NODE_ENV: production
API_KEY:
from_secret: api_key # Reference secret
commands:
- echo $NODE_ENV
- npm run buildSolution B: Pipeline-level environment:
```yaml kind: pipeline type: docker name: default
environment: NODE_ENV: test APP_VERSION: 1.0.0
steps: - name: build image: node:20 commands: - echo $NODE_ENV - echo $APP_VERSION ```
Solution C: Matrix builds with variables:
```yaml kind: pipeline type: docker name: default
matrix: NODE_VERSION: - 18 - 20 - 22
steps: - name: test image: node:${NODE_VERSION} commands: - node --version - npm test ```
Fix 5: Secret Management Errors
Secrets not accessible or incorrectly configured.
Symptoms:
- from_secret: ... returns empty
- Secrets don't get injected
Solution A: Define secrets in Drone:
Using Drone UI:
- 1.Go to your repository in Drone
- 2.Click "Settings" → "Secrets"
- 3.Add secrets (they're encrypted at rest)
Using CLI:
drone secret add --repository myorg/myrepo --name api_key --value my_secret_valueSolution B: Use secrets in pipeline:
steps:
- name: deploy
image: plugins/docker
settings:
repo: myorg/myrepo
username:
from_secret: docker_username
password:
from_secret: docker_passwordSolution C: External secret stores:
Drone can use external secret backends:
```yaml # Using Kubernetes secrets kind: secret name: kube_token get: path: kube-secrets name: token
# Using HashiCorp Vault kind: secret name: vault_secret get: path: vault/data/myapp name: password ```
Configure in Drone server:
DRONE_SECRET_PLUGIN_ENDPOINT=http://vault-plugin:3000Fix 6: Volume and Workspace Issues
Files not persisting between steps.
Symptoms: - Artifacts from one step not visible in next - Cache not working
Solution A: Use workspace correctly:
Drone automatically shares /drone/src between steps:
```yaml steps: - name: build image: node:20 commands: - npm ci - npm run build # Output goes to /drone/src/dist
- name: deploy
- image: alpine
- commands:
- - ls -la /drone/src/dist # Available from previous step
`
Solution B: Use volumes for caching:
```yaml kind: pipeline type: docker name: default
volumes: - name: npm_cache temp: {}
steps: - name: install image: node:20 volumes: - name: npm_cache path: /root/.npm commands: - npm ci --cache /root/.npm
- name: test
- image: node:20
- volumes:
- - name: npm_cache
- path: /root/.npm
- commands:
- - npm test
`
Solution C: Host volumes:
```yaml volumes: - name: global_cache host: path: /var/lib/drone/cache
steps: - name: build image: node:20 volumes: - name: global_cache path: /cache ```
Fix 7: Plugin Configuration Errors
Drone plugins have specific configuration requirements.
Symptoms: - Plugin fails silently - Settings not applied
Solution A: Use plugin settings correctly:
```yaml # Docker plugin - name: publish image: plugins/docker settings: repo: myorg/myrepo tags: latest dockerfile: Dockerfile username: from_secret: docker_username password: from_secret: docker_password
# SSH plugin - name: deploy image: appleboy/drone-ssh settings: host: deploy.company.com username: deploy password: from_secret: ssh_password script: - ./deploy.sh
# Slack notification - name: notify image: plugins/slack settings: webhook: from_secret: slack_webhook channel: builds template: "Build {{build.number}} completed" ```
Solution B: Check plugin documentation:
Each plugin has its own settings format. Check:
- plugins/docker: Docker Hub/registry publishing
- plugins/github-release: GitHub releases
- appleboy/drone-ssh: SSH deployments
- appleboy/drone-git-push: Git push
Fix 8: Trigger Conditions
Pipelines not triggering correctly.
Symptoms: - Build doesn't start on push - Wrong branches trigger builds - PRs not triggering
Solution A: Configure triggers:
```yaml kind: pipeline type: docker name: default
trigger: branch: - main - develop event: - push - pull_request ```
Solution B: Exclude events:
```yaml trigger: event: exclude: - tag # Don't run for tags
branch: exclude: - gh-pages ```
Solution C: Use conditions:
steps:
- name: deploy
image: alpine
when:
branch:
- main
event:
- push
commands:
- ./deploy.shFix 9: Resource Limits
Builds fail due to resource constraints.
Symptoms: - Out of memory - Timeout exceeded - Container killed
Solution A: Increase resources:
Drone containers inherit from Docker:
steps:
- name: build
image: node:20
commands:
- npm run buildFor self-hosted Drone, increase Docker daemon limits.
Solution B: Split into multiple pipelines:
```yaml kind: pipeline type: docker name: build
steps: - name: build image: node:20 commands: - npm run build
---
kind: pipeline type: docker name: test
steps: - name: test image: node:20 commands: - npm test
depends_on: - build ```
Solution C: Use timeout:
steps:
- name: long-test
image: node:20
commands:
- npm run test:e2e
failure: ignore # Don't fail pipeline if this step failsFix 10: Clone Step Failures
Repository clone fails.
Symptoms: - "fatal: could not read Username" - "repository not found" - Clone timeout
Solution A: Disable default clone:
```yaml kind: pipeline type: docker name: default
clone: disable: true
steps: - name: custom-clone image: alpine/git commands: - git clone https://github.com/myorg/myrepo.git . ```
Solution B: Configure clone depth:
```yaml clone: depth: 50 # Shallow clone
steps: - name: build image: node:20 commands: - npm run build ```
Solution C: Private repositories:
Drone server handles authentication for private repos:
# Configure in Drone server
DRONE_GITHUB_CLIENT_ID=...
DRONE_GITHUB_CLIENT_SECRET=...Quick Reference: Drone Errors
| Error | Cause | Solution |
|---|---|---|
| YAML parsing error | Old format or syntax | Use new format, validate YAML |
| Image pull failed | Registry/auth issue | Use correct image, configure auth |
command not found | Wrong base image | Use image with required tools |
| Secret empty | Not defined | Add secret in Drone UI |
| Volume not working | Missing config | Define volumes, use correct path |
| Build not triggering | Wrong trigger config | Set trigger conditions |
| Clone failed | Auth issue | Configure OAuth, check repo access |
Debugging Commands
Add to your pipeline:
steps:
- name: debug
image: alpine
commands:
- echo "=== Environment ==="
- env | sort
- echo "=== Workspace ==="
- pwd
- ls -la /drone/src
- echo "=== Drone Info ==="
- echo "Branch: $DRONE_BRANCH"
- echo "Commit: $DRONE_COMMIT"
- echo "Build: $DRONE_BUILD_NUMBER"