GC-201c · Module 1

Output Parsing & Error Handling

3 min read

Reliable automation requires robust output parsing and error handling. Gemini CLI's --output-format json produces structured output, but the content of the response is still natural language within that structure. The reliable pattern: constrain the prompt to produce a specific JSON schema, parse the outer JSON with jq or a script, then extract the structured fields from the response content. Double-layer parsing — first the transport format, then the content format.

Error handling in headless mode requires explicit checking. Gemini CLI returns non-zero exit codes for failures — authentication errors, rate limit hits, invalid prompts. Your scripts must check these codes. Additionally, the model can produce responses that are technically successful but semantically wrong — a review that says "no issues found" when there are obvious bugs. Build validation into your pipeline: check exit codes for infrastructure failures, and check response content for quality.

#!/bin/bash
# Robust headless execution with error handling

review_file() {
  local file="$1"
  local output
  local exit_code

  output=$(gemini -p "Review $file for bugs. Respond with JSON: {\"issues\": [{\"line\": N, \"severity\": \"high|medium|low\", \"description\": \"...\"}], \"clean\": true|false}" \
    --output-format json 2>/dev/null)
  exit_code=$?

  # Check infrastructure failure
  if [ $exit_code -ne 0 ]; then
    echo "ERROR: Gemini CLI failed for $file (exit code: $exit_code)" >&2
    return 1
  fi

  # Parse and validate response
  if echo "$output" | jq -e '.response' > /dev/null 2>&1; then
    echo "$output" | jq '.response'
  else
    echo "ERROR: Invalid JSON response for $file" >&2
    return 1
  fi
}

# Usage with error collection
failures=0
for file in src/**/*.ts; do
  if ! review_file "$file" >> review-results.json; then
    ((failures++))
  fi
done
echo "Completed with $failures failures"

Do This

  • Check exit codes for every headless invocation — failures are silent otherwise
  • Specify exact output schemas in prompts ("Respond with JSON: {fields...}")
  • Build retry logic for rate limit errors (exit code indicates retryable failure)

Avoid This

  • Assume every gemini -p call succeeds — network, auth, and rate limit failures happen
  • Let the model choose its output format — you will get inconsistent, unparseable results
  • Treat rate limit errors as permanent failures — they resolve with backoff