元渊 API元渊 API
Error Handling Guide

Core Error Indicators

Key criteria for detecting errors in Gemini API responses

Priority Detection Order

1️⃣ candidatesTokenCount = 0 (Highest Priority)

Most Reliable Indicator: Content review rejection

if (data.usageMetadata?.candidatesTokenCount === 0) {
    // Content rejected at review stage
    return { error: 'CONTENT_REVIEW_REJECTED' };
}

Characteristics:

  • Rejected before generation starts
  • finishReason may still be "STOP" (misleading!)
  • parts array is empty

2️⃣ finishReason != STOP (High Priority)

Values:

  • PROHIBITED_CONTENT - Violates policy
  • SAFETY - Triggers safety filter
  • RECITATION - Copyright concerns
  • MAX_TOKENS - Length exceeded
const finishReason = data.candidates[0].finishReason;
if (finishReason && finishReason !== 'STOP') {
    return { error: 'GENERATION_REJECTED', reason: finishReason };
}

3️⃣ Text Response (Medium Priority)

No image data, only text explanation

const parts = data.candidates[0].content.parts;
const hasImage = parts.some(p => p.inlineData?.data);
const hasText = parts.some(p => p.text);

if (!hasImage && hasText) {
    return { error: 'TEXT_RESPONSE', text: parts[0].text };
}

4️⃣ Knowledge Cutoff (Low Priority)

Model mentions knowledge limitations

if (text.includes("knowledge cutoff") || 
    text.includes("after April 2023")) {
    return { error: 'KNOWLEDGE_CUTOFF' };
}

Detection Flow

function detectError(data) {
    // 1. Content review
    if (data.usageMetadata?.candidatesTokenCount === 0) {
        return 'CONTENT_REVIEW_REJECTED';
    }
    
    // 2. Generation rejection
    const finishReason = data.candidates?.[0]?.finishReason;
    if (finishReason && finishReason !== 'STOP') {
        return `FINISH_REASON_${finishReason}`;
    }
    
    // 3. Check parts
    const parts = data.candidates?.[0]?.content?.parts || [];
    const hasImage = parts.some(p => p.inlineData?.data);
    
    if (hasImage) {
        return 'SUCCESS';
    }
    
    // 4. Text response
    if (parts.some(p => p.text)) {
        return 'TEXT_RESPONSE';
    }
    
    return 'UNKNOWN_ERROR';
}

Common Pitfalls

Don't check finishReason === "STOP" first
Do check candidatesTokenCount first

Don't assume empty parts means error
Do check candidatesTokenCount to distinguish

Don't ignore text responses
Do parse and display rejection reasons

How is this guide?