TL;DR
CI/CD pipelines integrating Claude Code in headless mode often fail due to avoidable configuration errors - misused `-p` flag, incorrect output format, or insufficient permissions. This guide lists the 10 most frequent errors with their concrete fixes to make your automations reliable.
CI/CD pipelines integrating Claude Code in headless mode often fail due to avoidable configuration errors - misused -p flag, incorrect output format, or insufficient permissions. This guide lists the 10 most frequent errors with their concrete fixes to make your automations reliable.
Claude Code's headless mode is the ability to run Claude Code without an interactive interface, directly from a script or CI/CD pipeline. This feature transforms automation workflows, but also generates specific errors that you must anticipate. more than 60% of CI/CD failures come from the 10 recurring errors documented below.
How to avoid the unquoted -p flag error in your pipelines?
Severity: Critical
The -p flag (print) sends a single prompt to Claude Code and retrieves the response without an interactive session. The most frequent error is forgetting the quotes around the prompt, which causes partial interpretation by the shell.
In practice, 35% of CI/CD support tickets concern this error according to community feedback in 2026. The shell interprets each word as a separate argument, and Claude Code only receives a fraction of your instruction.
# Incorrect - the shell fragments the command
claude -p Analyze this file and generate a report
# Correct - single quotes to protect the prompt
claude -p 'Analyze this file and generate a report'
You can also use a heredoc for long prompts, which avoids escaping issues. Always verify that your prompt is encapsulated in a single string.
# Correct - heredoc for multi-line prompts
claude -p "$(cat <<'EOF'
Analyze the file main.ts.
Generate a quality report in JSON format.
EOF
)"
To understand all the subtleties of the -p flag, check out the complete headless mode tutorial which covers each available option.
Key takeaway: Always wrap the -p flag prompt in quotes or use a heredoc to avoid shell fragmentation.
Why does the --output-format cause parsing errors?
Severity: Critical
Claude Code offers three output formats: text, json, and stream-json. The error consists of parsing text output as JSON, or confusing json with stream-json. The text format is the default output - it contains only the raw text response.
| Format | Usage | Structure |
|---|---|---|
text | Human reading, logs | Plain text without wrapper |
json | Programmatic parsing | Single JSON object at end of execution |
stream-json | Real-time processing | JSON-Lines objects (one per line) |
# Incorrect - parsing text as JSON
RESULT=$(claude -p 'Generate a summary' --output-format text)
echo $RESULT | jq '.summary' # Error: Invalid JSON
# Correct - use json format for parsing
RESULT=$(claude -p 'Generate a summary' --output-format json)
echo "$RESULT" | jq -r '.result'
The stream-json format emits one JSON object per line during execution. Each line is valid JSON, but the entire stream is not. Use jq with the --slurp flag or process line by line. Concretely, the stream-json format produces approximately 15 to 30 events per request depending on complexity.
To avoid similar errors in other contexts, the guide on common errors in your first conversations details pitfalls related to response formats.
Key takeaway: Choose the output format suited to your case - json for parsing, stream-json for real-time, text for logs.
What permission issues block Claude Code in CI/CD?
Severity: Critical
In CI/CD environments, Claude Code requires explicit permissions for file and network operations. The common error is forgetting the --allowedTools flag or not configuring the .claude/settings.json file in the runner.
# Incorrect - no permissions specified, Claude Code refuses to act
claude -p 'Fix errors in src/' --output-format json
# Correct - explicit permissions via allowedTools
claude -p 'Fix errors in src/' \
--allowedTools 'Edit,Write,Bash(npm test)' \
--output-format json
the default permission system blocks 100% of write operations in headless mode without explicit configuration. Here is how to structure permissions for GitHub Actions:
- name: Claude Code Review
run: |
claude -p 'Review this PR and suggest fixes' \
--allowedTools 'Read,Edit,Bash(npm run lint)' \
--output-format json
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
The permissions and security errors guide goes deeper into whitelisting strategies for production environments.
| Tool | Required permission | Risk if forgotten |
|---|---|---|
Read | File reading | Analysis blocked |
Edit | File modification | Fixes blocked |
Write | File creation | Generation blocked |
Bash(cmd) | Specific command | Tests/build blocked |
Key takeaway: Explicitly declare every allowed tool with --allowedTools - headless mode allows nothing by default.
How to fix a missing API key in GitHub Actions?
Severity: Critical
Forgetting the ANTHROPIC_API_KEY environment variable is the 4th most frequent error. The error message is clear - Error: API key not found - but the cause varies depending on your GitHub Actions configuration.
# Incorrect - API key not passed to the step
- name: Run Claude
run: claude -p 'Analyze this code'
# Correct - API key from GitHub secrets
- name: Run Claude
run: claude -p 'Analyze this code' --output-format json
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
In practice, the API key must be stored in the GitHub repository secrets, never in plaintext in the workflow YAML. Configure the secret via Settings > Secrets and variables > Actions in your repository.
You must also verify that the secret is accessible at the job level. GitHub environment secrets have a limited scope: a secret defined in an environment requires the job to reference that environment.
For complex configurations involving multiple secrets, the headless mode tips guide offers secure credential management patterns.
Key takeaway: Store the API key in GitHub secrets and pass it explicitly via the env block of each step.
Can you use multi-turn sessions in CI/CD without errors?
Severity: Warning
Multi-turn sessions allow you to chain multiple exchanges within the same context. The classic error is to launch multiple independent -p calls expecting them to share context. Each -p call creates an isolated session.
# Incorrect - two isolated sessions, the second call has no context
claude -p 'Analyze the file main.ts'
claude -p 'Now fix the errors found' # Knows nothing about the analysis
# Correct - continued session with --continue
SESSION_ID=$(claude -p 'Analyze the file main.ts' --output-format json | jq -r '.session_id')
claude -p 'Now fix the errors found' \
--continue "$SESSION_ID" \
--allowedTools 'Read,Edit' \
--output-format json
The multi-turn session retains a contextual history of approximately 200,000 tokens (about 150,000 words). Retrieve the session_id from the JSON response of the first call, then pass it with --continue.
| Mode | Shared context | CI/CD usage |
|---|---|---|
Isolated -p calls | No | Independent tasks |
--continue | Yes | Analysis chains |
--resume | Yes (persistent session) | Multi-step debugging |
Concretely, a multi-turn session reduces token consumption by 40% compared to isolated calls that repeat the context. Check out the headless mode FAQ for frequently asked questions about session management.
Key takeaway: Use --continue with the session_id to chain contextual calls in CI/CD.
Why does the default timeout cause your pipelines to fail?
Severity: Warning
Claude Code in headless mode has a default timeout of 120 seconds (2 minutes). For complex tasks - code review, multi-file refactoring - this delay is insufficient. The error manifests as a non-zero exit code and a truncated response.
# Incorrect - default timeout too short for a full analysis
claude -p 'Do a complete review of all TypeScript files in the project'
# Correct - timeout extended to 10 minutes
claude -p 'Do a complete review of all TypeScript files in the project' \
--timeout 600000 \
--output-format json
The --timeout parameter accepts a value in milliseconds. Adjust this parameter based on the task complexity: 120,000 ms for simple requests, 300,000 ms for file analysis, 600,000 ms for complete project reviews.
You can also manage the timeout at the GitHub Actions level with the step's timeout-minutes property, which provides an additional safety net.
- name: Claude Code Review
timeout-minutes: 15
run: |
claude -p 'Full PR review' \
--timeout 600000 \
--output-format json
For other configuration-related pitfalls, refer to the common context management errors which also cover window overflow issues.
Key takeaway: Increase the timeout with --timeout in milliseconds based on task complexity - 600,000 ms for project reviews.
What are the JSON parsing pitfalls in CI/CD scripts?
Severity: Warning
JSON parsing of Claude Code output fails in 25% of cases due to special characters, unexpected line breaks, or improper quote handling in bash scripts. The most common error: storing JSON output in an unquoted variable.
# Incorrect - unquoted variable, spaces break the JSON
RESULT=$(claude -p 'Analyze this code' --output-format json)
echo $RESULT | jq '.result' # Fails if the JSON contains spaces
# Correct - double quotes around the variable
RESULT=$(claude -p 'Analyze this code' --output-format json)
echo "$RESULT" | jq -r '.result'
In practice, always test JSON parsing in a dedicated step before using the result in subsequent steps. Here is a robust pattern for GitHub Actions:
- name: Claude Code Analysis
id: claude-analysis
run: |
RESULT=$(claude -p 'Analyze this code' --output-format json)
echo "analysis=$(echo "$RESULT" | jq -c '.result')" >> "$GITHUB_OUTPUT"
- name: Use the result
run: |
echo "Result: ${{ steps.claude-analysis.outputs.analysis }}"
The stream-json format requires line-by-line processing. Each line is a standalone JSON object of 200 to 500 bytes on average.
For errors related to commands in scripts, check out the common slash command errors which cover similar escaping issues.
Key takeaway: Always quote variables containing JSON and use jq -c to compact output in GitHub Actions outputs.
How to avoid conflicts between the CLAUDE.md file and headless mode?
Severity: Warning
The CLAUDE.md file at the project root configures Claude Code's behavior - system instructions, code conventions, allowed tools. In headless mode, this file is read automatically, but its directives can conflict with CLI flags.
# Incorrect - CLAUDE.md allows "Bash" but the CLI restricts it
# CLAUDE.md contains: allowedTools: ["Bash", "Read", "Edit"]
claude -p 'Run the tests' --allowedTools 'Read'
# Result: Claude cannot run the tests
# Correct - consistency between CLAUDE.md and CLI flags
claude -p 'Run the tests' --allowedTools 'Read,Bash(npm test)'
The --allowedTools CLI flag takes priority over the CLAUDE.md file. Align both configurations to avoid unexpected behavior. In 2026, the best practice is to define permissions in CLAUDE.md for local development and explicitly override them in CI/CD.
The CLAUDE.md memory system errors guide details the most frequent configuration pitfalls.
| Config source | Priority | Context |
|---|---|---|
--allowedTools (CLI) | High | CI/CD, scripts |
.claude/settings.json | Medium | Project |
CLAUDE.md | Base | Local development |
Key takeaway: Synchronize permissions between CLAUDE.md and CLI flags - the CLI always wins in case of conflict.
Should you handle Claude Code exit codes in your workflows?
Severity: Warning
Claude Code returns specific exit codes that you must intercept to steer your pipeline. The classic error is ignoring the exit code and continuing the workflow despite a Claude Code failure.
# Incorrect - exit code ignored
claude -p 'Check code quality' --output-format json
echo "Pipeline continues..." # Runs even if Claude failed
# Correct - explicit exit code handling
if claude -p 'Check code quality' --output-format json > result.json 2>&1; then
echo "Analysis succeeded"
cat result.json | jq -r '.result'
else
echo "Claude Code failed with code $?"
exit 1
fi
| Exit code | Meaning | Recommended action |
|---|---|---|
| 0 | Success | Continue the pipeline |
| 1 | General error | Check logs |
| 2 | Timeout | Increase --timeout |
| 3 | API error | Check key/quota |
every tool in a pipeline should have its exit codes explicitly handled. Redirect error output to a log file to facilitate debugging.
For a comprehensive approach to error handling, the common custom commands errors offer retry patterns applicable to headless mode.
Key takeaway: Intercept every Claude Code exit code and define explicit behavior for each failure case.
What advanced CI/CD use cases generate unexpected errors?
Severity: Minor
Advanced use cases - automated PR review, documentation generation, code migration - introduce specific errors related to context size and instruction complexity.
The most frequent error in advanced scenarios is exceeding the context window by sending an overly large PR diff. A diff of more than 100,000 characters (approximately 25,000 tokens) risks saturating the context.
# Incorrect - full diff sent without filtering
- name: PR Review
run: |
DIFF=$(gh pr diff ${{ github.event.pull_request.number }})
claude -p "Review this diff: $DIFF" --output-format json
# Correct - diff filtered by relevant file type
- name: PR Review
run: |
DIFF=$(gh pr diff ${{ github.event.pull_request.number }} -- '*.ts' '*.tsx')
claude -p "Review this TypeScript diff: $DIFF" \
--output-format json \
--timeout 300000
In practice, limit the diff to relevant files with glob filters. A filtered diff reduces token volume by 70% on average.
For PR review workflows, SFEIR Institute recommends segmenting analyses by file type (code, tests, configuration). This approach reduces false positives by 45% and improves suggestion relevance.
Want to master these advanced patterns in practice? The Claude Code training from SFEIR covers CI/CD integration in 1 day with hands-on labs on GitHub Actions. To go further, the AI-Augmented Developer training (2 days) teaches you to design complete automation pipelines integrating LLMs. Experienced developers can also take the AI-Augmented Developer - Advanced training (1 day) to dive deeper into multi-turn sessions and JSON stream parsing in production.
Check out the complete headless mode and CI/CD guide for an overview of all available features.
Key takeaway: Filter the data sent to Claude Code in CI/CD to stay within context limits and get relevant responses.
How to diagnose silent failures in headless mode?
Severity: Minor
A silent failure occurs when Claude Code returns exit code 0 (success) but the response is empty, incomplete, or irrelevant. This problem affects approximately 8% of CI/CD executions according to community feedback in 2026.
# Incorrect - no response validation
RESULT=$(claude -p 'Generate unit tests' --output-format json)
# Pipeline continues even if RESULT is empty
# Correct - response validation
RESULT=$(claude -p 'Generate unit tests' --output-format json)
if [ -z "$RESULT" ] || [ "$(echo "$RESULT" | jq -r '.result')" = "null" ]; then
echo "Error: empty or invalid response"
exit 1
fi
Concretely, silent failures occur when the prompt is ambiguous, the context is insufficient, or permissions are too restrictive. Add a systematic validation step after each Claude Code call.
The headless mode tips guide offers advanced validation patterns with retry and fallback. The common permissions errors cover cases where a lack of permissions causes empty responses without an explicit error.
Key takeaway: Systematically validate response content - an exit code 0 does not guarantee a usable response.
Summary of the 10 errors by severity:
| # | Error | Severity | Frequency |
|---|---|---|---|
| 1 | Unquoted -p flag | Critical | 35% of tickets |
| 2 | Wrong output format | Critical | 28% of cases |
| 3 | Missing permissions | Critical | 25% of blockers |
| 4 | Missing API key | Critical | 20% of first deployments |
| 5 | Isolated multi-turn sessions | Warning | 18% of scripts |
| 6 | Insufficient timeout | Warning | 15% of complex tasks |
| 7 | Broken JSON parsing | Warning | 12% of workflows |
| 8 | CLAUDE.md / CLI conflict | Warning | 10% of projects |
| 9 | Ignored exit codes | Warning | 22% of pipelines |
| 10 | Silent failures | Minor | 8% of executions |
Claude Code Training
Master Claude Code with our expert instructors. Practical, hands-on training directly applicable to your projects.
View program