shell-error-handling
Use when implementing error handling, cleanup routines, or debugging in shell scripts. Covers traps, exit codes, and robust error patterns.
What this skill does
# Shell Error Handling
Patterns for robust error handling, cleanup, and debugging in shell scripts.
## Exit Codes
### Standard Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | General error |
| 2 | Misuse of shell command |
| 126 | Command not executable |
| 127 | Command not found |
| 128+N | Fatal signal N |
| 130 | Ctrl+C (SIGINT) |
### Checking Exit Status
```bash
# Check last command's exit status
if ! command; then
echo "Command failed with status $?" >&2
exit 1
fi
# Alternative pattern
command || {
echo "Command failed" >&2
exit 1
}
# Capture exit status
command
status=$?
if (( status != 0 )); then
echo "Failed with status $status" >&2
fi
```
## Trap for Cleanup
### Basic Cleanup Pattern
```bash
#!/usr/bin/env bash
set -euo pipefail
cleanup() {
local exit_code=$?
# Remove temporary files
rm -f "$TEMP_FILE" 2>/dev/null || true
exit "$exit_code"
}
trap cleanup EXIT
TEMP_FILE=$(mktemp)
# Script continues...
# cleanup runs automatically on exit
```
### Handling Multiple Signals
```bash
#!/usr/bin/env bash
set -euo pipefail
cleanup() {
echo "Cleaning up..." >&2
rm -rf "$WORK_DIR" 2>/dev/null || true
}
handle_interrupt() {
echo "Interrupted by user" >&2
cleanup
exit 130
}
trap cleanup EXIT
trap handle_interrupt INT TERM
WORK_DIR=$(mktemp -d)
```
### Trap Best Practices
```bash
# Preserve original exit code in cleanup
cleanup() {
local exit_code=$?
# Cleanup operations here
rm -f "$temp_file" 2>/dev/null || true
# Restore exit code
exit "$exit_code"
}
# Use || true for optional cleanup
trap 'rm -f "$temp_file" 2>/dev/null || true' EXIT
```
## Error Reporting
### Standard Error Output
```bash
# Always write errors to stderr
echo "Error: Something went wrong" >&2
# Error function
error() {
echo "Error: $*" >&2
}
# Die function - error and exit
die() {
echo "Fatal: $*" >&2
exit 1
}
# Usage
[[ -f "$config" ]] || die "Config file not found: $config"
```
### Verbose Logging
```bash
#!/usr/bin/env bash
set -euo pipefail
VERBOSE="${VERBOSE:-false}"
log() {
if [[ "$VERBOSE" == "true" ]]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
fi
}
error() {
echo "[ERROR] $*" >&2
}
log "Starting script"
log "Processing file: $file"
```
## Defensive Programming
### Check Prerequisites
```bash
# Check required commands exist
require_command() {
command -v "$1" >/dev/null 2>&1 || {
echo "Error: Required command '$1' not found" >&2
exit 1
}
}
require_command jq
require_command curl
require_command shellcheck
```
### Validate Input
```bash
# Validate arguments
if [[ $# -lt 2 ]]; then
echo "Usage: $0 <source> <destination>" >&2
exit 1
fi
source_file="$1"
dest_dir="$2"
# Validate file exists
[[ -f "$source_file" ]] || {
echo "Error: Source file not found: $source_file" >&2
exit 1
}
# Validate directory
[[ -d "$dest_dir" ]] || {
echo "Error: Destination directory not found: $dest_dir" >&2
exit 1
}
```
### Safe Temporary Files
```bash
# Create secure temp file
TEMP_FILE=$(mktemp) || {
echo "Error: Failed to create temp file" >&2
exit 1
}
# Create secure temp directory
TEMP_DIR=$(mktemp -d) || {
echo "Error: Failed to create temp directory" >&2
exit 1
}
# Always clean up
trap 'rm -rf "$TEMP_FILE" "$TEMP_DIR" 2>/dev/null || true' EXIT
```
## Debugging
### Debug Mode
```bash
#!/usr/bin/env bash
# Enable debug mode via environment variable
if [[ "${DEBUG:-}" == "1" ]]; then
set -x
fi
set -euo pipefail
# Or toggle with a flag
while getopts "d" opt; do
case $opt in
d) set -x ;;
*) echo "Usage: $0 [-d]" >&2; exit 1 ;;
esac
done
```
### Trace Execution
```bash
# Enable tracing for specific section
set -x
problematic_code
set +x
# Trace with custom PS4
export PS4='+ ${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -x
```
## Error Recovery Patterns
### Retry Pattern
```bash
retry() {
local max_attempts="${1:-3}"
local delay="${2:-1}"
shift 2
local cmd=("$@")
local attempt=1
while (( attempt <= max_attempts )); do
if "${cmd[@]}"; then
return 0
fi
echo "Attempt $attempt failed, retrying in ${delay}s..." >&2
sleep "$delay"
(( attempt++ ))
done
echo "All $max_attempts attempts failed" >&2
return 1
}
# Usage
retry 3 5 curl -f "http://example.com/api"
```
### Fallback Pattern
```bash
# Try primary, fall back to secondary
get_config() {
if [[ -f "$HOME/.config/myapp/config" ]]; then
cat "$HOME/.config/myapp/config"
elif [[ -f "/etc/myapp/config" ]]; then
cat "/etc/myapp/config"
else
echo "Error: No config file found" >&2
return 1
fi
}
```
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.