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