Skip to main content
The CLI provides structured error handling with predictable exit codes following CI/CD best practices.

Exit Codes

Every command returns a numeric exit code that indicates the result:
asc apps list
echo $?  # 0 = success

Exit Code Reference

CodeMeaningExample
0SuccessCommand completed successfully
1Generic errorUnexpected failure, network error, or unknown issue
2Usage errorInvalid flags, missing required arguments, or malformed command
3Authentication failureMissing credentials, invalid API key, or permission denied
4Resource not foundApp, build, or resource does not exist
5ConflictResource already exists or version conflict

HTTP Status Mapping

The CLI maps HTTP status codes to exit codes:

4xx Client Errors

Formula: 10 + (status - 400)
HTTP StatusExit CodeDescription
400 Bad Request10Invalid request parameters
401 Unauthorized11Authentication required
403 Forbidden12Permission denied
404 Not Found4Resource not found (special case)
409 Conflict5Resource conflict (special case)
422 Unprocessable22Validation error

5xx Server Errors

Formula: 60 + (status - 500)
HTTP StatusExit CodeDescription
500 Internal Server Error60API server error
502 Bad Gateway62Gateway error
503 Service Unavailable63Service temporarily unavailable
Exit codes follow a deterministic formula defined in cmd/exit_codes.go. This ensures consistent, scriptable error handling.

API Errors

The App Store Connect API returns structured error responses:
{
  "errors": [
    {
      "status": "404",
      "code": "NOT_FOUND",
      "title": "The requested resource does not exist",
      "detail": "There is no app with ID '123456789'"
    }
  ]
}
The CLI parses these errors and displays them in a human-readable format:
asc apps get --id 123456789
# Error: The requested resource does not exist: There is no app with ID '123456789'
# Exit code: 4

Well-Known Error Codes

The CLI recognizes standard App Store Connect error codes:
  • NOT_FOUND → Exit code 4
  • CONFLICT → Exit code 5
  • UNAUTHORIZED → Exit code 3
  • FORBIDDEN → Exit code 3
  • BAD_REQUEST → Exit code 10
These map to Go error sentinels:
// From internal/asc/errors.go
var (
    ErrNotFound     = errors.New("resource not found")
    ErrUnauthorized = errors.New("unauthorized")
    ErrForbidden    = errors.New("forbidden")
    ErrBadRequest   = errors.New("bad request")
    ErrConflict     = errors.New("resource conflict")
)

Associated Errors

Some API errors include additional details under meta.associatedErrors:
asc versions create --app APP_ID --version 1.0.0 --platform IOS
# Error: Version creation failed: The version string is invalid
# 
# Associated errors for appStoreVersion:
#   - Version string must follow semantic versioning (e.g., 1.0.0)
#   - Version 1.0.0 already exists for this app
The CLI formats these errors with clear indentation and grouping.

Error Messages

All error messages go to stderr, not stdout:
# Success: data goes to stdout
asc apps list --output json > apps.json

# Failure: error goes to stderr, stdout is empty
asc apps get --id INVALID 2> error.log
# error.log contains: "Error: The requested resource does not exist: ..."
This allows safe piping and redirection:
# Pipe only successful output
asc apps list --output json | jq '.data[0].id'

# Capture errors separately
asc apps get --id APP_ID > output.json 2> errors.log

Handling Errors in Scripts

Exit Code Checks

#!/bin/bash
set -e  # Exit on any error

asc apps list --output json > apps.json
if [ $? -eq 0 ]; then
  echo "Success: $(jq '.data | length' apps.json) apps found"
fi

Specific Error Handling

#!/bin/bash
asc apps get --id "$APP_ID" --output json > app.json
EXIT_CODE=$?

case $EXIT_CODE in
  0)
    echo "App found"
    ;;
  4)
    echo "App not found, creating..."
    asc apps create --name "My App" --bundle-id "com.example.app"
    ;;
  3)
    echo "Authentication failed. Check ASC_KEY_ID and ASC_ISSUER_ID."
    exit 1
    ;;
  *)
    echo "Unexpected error (exit code: $EXIT_CODE)"
    exit 1
    ;;
esac

Retry on Transient Errors

#!/bin/bash
retry_count=0
max_retries=3

while [ $retry_count -lt $max_retries ]; do
  asc apps list --output json > apps.json
  exit_code=$?
  
  # Success
  if [ $exit_code -eq 0 ]; then
    break
  fi
  
  # Retry on 5xx errors (exit codes 60-99)
  if [ $exit_code -ge 60 ] && [ $exit_code -le 99 ]; then
    retry_count=$((retry_count + 1))
    echo "Server error, retrying ($retry_count/$max_retries)..." >&2
    sleep 5
  else
    # Non-retryable error
    echo "Fatal error (exit code: $exit_code)" >&2
    exit $exit_code
  fi
done

CI/CD Integration

GitHub Actions

- name: Fetch apps
  id: fetch_apps
  run: |
    asc apps list --output json > apps.json
  continue-on-error: true

- name: Handle errors
  if: failure()
  run: |
    echo "Failed to fetch apps (exit code: $?)"
    exit 1

GitLab CI

fetch_apps:
  script:
    - asc apps list --output json > apps.json
  allow_failure:
    exit_codes:
      - 4  # Allow not found

Makefile

.PHONY: check-auth
check-auth:
	@asc auth status --output json > /dev/null 2>&1 || \
	  (echo "Error: Authentication failed. Run 'asc auth login'"; exit 1)

.PHONY: list-apps
list-apps: check-auth
	asc apps list --output json > apps.json

Authentication Errors

Common authentication failures and solutions:

Missing Credentials

asc apps list
# Error: missing authentication. Run 'asc auth login' or 'asc auth init'
# Exit code: 1 (generic error, not 3)
Missing credentials return exit code 1, not 3. Exit code 3 is reserved for failed authentication (invalid credentials), not missing credentials.

Invalid API Key

asc apps list
# Error: unauthorized
# Exit code: 3
Solution: Verify your credentials:
asc auth status

Permission Denied

asc apps delete --id APP_ID --confirm
# Error: forbidden: You don't have permission to delete apps
# Exit code: 3
Solution: Check your App Store Connect role and permissions.

Debugging Errors

Enable debug logging with --debug or --api-debug:
# General debug output
asc apps list --debug

# HTTP request/response debug (redacts sensitive values)
asc apps list --api-debug
Debug output goes to stderr:
asc apps list --api-debug 2> debug.log

Environment Variables

# Enable API debug for all commands
export ASC_DEBUG=api
asc apps list

# Disable debug
unset ASC_DEBUG

Error Handling Best Practices

Always Check Exit Codes

Use set -e in shell scripts or check $? after each command.

Separate stdout and stderr

Redirect errors to a log file: asc apps list 2> errors.log.

Handle Expected Errors

Exit code 4 (not found) is often expected. Handle it explicitly.

Retry Transient Errors

Retry on exit codes 60-99 (5xx server errors) with exponential backoff.