Kimi K2.7 Code is now on CometAPI — Kimi's most intelligent coding model to date, reliably follows instructions in long contexts and completes programming tasks with a higher success rate. Try it now

Başarısız AI API oluşturma işlemleri nasıl hata ayıklanır

CometAPI
AnnaJun 4, 2026
Başarısız AI API oluşturma işlemleri nasıl hata ayıklanır

Yapay zeka API başarısızlıkları, normal API başarısızlıklarından farklıdır. 200 yanıtı, üretiminizin başarılı olduğu anlamına gelmez. null content alanı her zaman bir hata değildir. Ve dün çalışan aynı istem, bir sağlayıcı içerik politikasını güncellediği için bugün başarısız olabilir.

Bu kılavuz, yapay zeka API hatalarını nasıl okuyacağınızı, her bir başarısızlık modunun gerçekte ne anlama geldiğini ve “bir şeyler bozuldu” demek yerine “neyin bozulduğunu” söyleyen hata yakalama mantığını nasıl kuracağınızı kapsar.

Not: Bu yazıda kullanılan gpt-5.4 ve gpt-5.4-mini gibi model adları CometAPI’nin platform tanımlayıcılarıdır. Yalnızca https://api.cometapi.com/v1 üzerinden çalışırlar — OpenAI veya Anthropic’in API’leri üzerinden doğrudan çalışmazlar. tam model listesine bakın.

Yapay zeka API hata ayıklaması neden normal API hata ayıklamasından daha zordur

Tipik bir REST API’de 200 başarı, 4xx ise sizin bir şeyi yanlış yaptığınız anlamına gelir. Yapay zeka API’leri üçüncü bir kategori ekler: 200 dönen fakat kullanılabilir içerik içermeyen yanıtlar — yani yumuşak başarısızlıklar.

Üç şey ters gidebilir:

  1. Ciddi başarısızlık — HTTP hatası (4xx, 5xx). İstek tamamlanmadı.
  2. Yumuşak başarısızlık — HTTP 200, ancak finish_reason content_filter veya length, ya da content null.
  3. Sessiz başarısızlık — HTTP 200, içerik düzgün görünüyor, ancak çıktı sadece uygulama katmanında yakalayabileceğiniz şekilde hatalı.

Hata yakalama mantığının çoğu yalnızca 1. durumu kapsar. 2 ve 3. durumlar ise üretimdeki hataların çoğunun yaşandığı yerlerdir.

Hata yanıtı biçimini anlayın

Metin tamamlama uç noktası tutarlı bir hata yapısı döndürür:

{  "error": {    "message": "human-readable description (often includes request id)",    "type": "comet_api_error",    "param": "the_problematic_parameter_or_null",    "code": "error_code_or_null"  }}

Görüntü ve video uç noktaları farklı hata biçimleri döndürür — uç noktalar arasında sabit bir yapıyı varsaymak yerine her zaman ham yanıt gövdesini ayrıştırın.

message alanı genellikle sorunun ne olduğunu açıkça söyler. param alanı hangi parametrenin buna sebep olduğunu belirtir. Her ikisini de mutlaka kaydedin.

Her HTTP durum kodunun ne anlama geldiğini bilin

DurumAnlamıYaygın nedenÇözüm
400Kötü istekEksik model, bu model için yanlış parametreYanttaki error.param değerini kontrol edin
401YetkisizHatalı veya eksik API anahtarıAuthorization: Bearer biçimini doğrulayın
429Oran sınırıÇok fazla istekÜssel geri çekilme (bkz. Adım 4)
500Sunucu hatasıSağlayıcı tarafı sorun veya hatalı istek gövdesiGeri çekilerek yeniden deneyin; istek biçimini kontrol edin
504Ağ geçidi zaman aşımıSağlayıcı çok uzun sürdüYeniden deneyin; daha hızlı bir model düşünün

Kaynak**:* CometAPI chat completions docs

Yeniden deneme mantığı için 400 ile 500 ayrımı önemlidir. 400 isteğinizin hatalı olduğunu ifade eder — aynı isteği yeniden denemek yardımcı olmaz. 500 veya 504 sunucunun bir sorunu olduğu anlamına gelir — yeniden denemek mantıklıdır.

finish_reason alanını kontrol edin — en gözden kaçan alan

finish_reason: "content_filter" ile gelen bir 200 yanıtı, üretiminizin engellendiği anlamına gelir. content alanı null ya da boştur. Bunu kontrol etmezseniz, uygulamanız sessizce hiçbir şey döndürür.

finish_reasonAnlamıNe yapmalıÇözüm
stopNormal tamamlamaGerek yok — bu başarıYanttaki error.param değerini kontrol edin
lengthToken sınırına ulaşıldımax_tokens'ı artırın veya istemi kısaltınAuthorization: Bearer biçimini doğrulayın
content_filterGüvenlik politikası tarafından engellendiİstemi yeniden ifade edin; belirli isim/konulardan kaçınınÜssel geri çekilme (bkz. Adım 4)
tool_callsModel metin dönmek yerine bir araç çağırdıAraç çağrısını işleyin; content null olacaktırGeri çekilerek yeniden deneyin; istek biçimini kontrol edin
504Ağ geçidi zaman aşımıSağlayıcı çok uzun sürdüYeniden deneyin; daha hızlı bir model düşünün

Kaynak**:* CometAPI chat completions docs

import osimport loggingfrom openai import OpenAI, APIStatusError, APIConnectionError, APITimeoutErrorfrom dotenv import load_dotenv​load_dotenv()​api_key = os.environ.get("COMETAPI_KEY")if not api_key:    raise ValueError("COMETAPI_KEY is not set")​client = OpenAI(    base_url="https://api.cometapi.com/v1",    api_key=api_key,)​def safe_complete(messages: list, model: str = "gpt-5.4-mini", **kwargs) -> dict:    """    Complete a chat request with full error and finish_reason handling.    Returns {"content": str, "finish_reason": str, "tool_calls": list | None}    Raises on API errors.    """    try:        response = client.chat.completions.create(            model=model,            messages=messages,            **kwargs        )    except APIStatusError as e:        error_body = {}        try:            error_body = e.response.json().get("error", {})        except Exception:            pass        logging.error(            f"API error status={e.status_code} "            f"message={error_body.get('message')} "            f"param={error_body.get('param')}"        )        raise    except (APIConnectionError, APITimeoutError) as e:        logging.error(f"Network/timeout error: {e}")        raise​    choice = response.choices[0]    finish_reason = choice.finish_reason​    if finish_reason == "content_filter":        raise ValueError(            f"Generation blocked by content filter. "            f"Model: {model}. Rephrase the prompt."        )​    if finish_reason == "length":        used = response.usage.completion_tokens if response.usage else "unknown"        logging.warning(f"Output truncated at token limit. Used {used} tokens.")​    # Return structured result so callers can handle tool_calls explicitly    return {        "content": choice.message.content or "",        "finish_reason": finish_reason,        "tool_calls": choice.message.tool_calls,    }​# Usageresult = safe_complete(    messages=[{"role": "user", "content": "Summarize this article: [text]"}],    model="gpt-5.4-mini")​if result["finish_reason"] == "tool_calls":    # Handle tool call — content will be empty    print("Model wants to call a tool:", result["tool_calls"])else:    print(result["content"])

Sessiz başarısızlıkları uygulama katmanında tespit edin

Sessiz başarısızlıklar yakalaması en zor olanlardır. API 200 döndürür, finish_reason stop olur, ancak çıktı anlamsal olarak yanlıştır. Bunları yalnızca uygulama katmanında yakalayabilirsiniz.

Yaygın kalıplar:

def validate_completion(result: dict, task: str) -> str:    """    Application-layer validation for silent failures.    Raises ValueError if the output doesn't meet basic expectations.    """    content = result["content"].strip()​    # Empty output that isn't a tool call    if not content and result["finish_reason"] != "tool_calls":        raise ValueError(f"Empty output for task '{task}' with finish_reason='{result['finish_reason']}'")​    # Task-specific checks    if task == "classify":        valid_labels = {"positive", "negative", "neutral"}        if content.lower() not in valid_labels:            logging.warning(                f"Unexpected classification output: '{content}'. "                f"Expected one of {valid_labels}. "                f"Model may have returned explanation instead of label."            )​    if task == "json_extract":        import json        try:            json.loads(content)        except json.JSONDecodeError:            raise ValueError(                f"Expected JSON output but got: '{content[:100]}...'. "                f"Try adding 'respond with valid JSON only' to the prompt, "                f"or use response_format={{\"type\": \"json_object\"}}."            )​    if task == "summarize" and len(content.split()) < 10:        logging.warning(            f"Suspiciously short summary ({len(content.split())} words). "            f"Check if the input was too short or the model misunderstood the task."        )​    return content​​# Full flow with silent failure detectionresult = safe_complete(    messages=[{"role": "user", "content": "Classify as positive/negative/neutral: 'Great product!'"}],    model="claude-haiku-4-5")label = validate_completion(result, task="classify")

Sessiz başarısızlıklar genellikle üç kaynaktan birinden gelir: istem belirsizdir, model biçim talimatlarınızı yok saymıştır veya girdi görev için çok kısa/uzundur. Doğru olanı teşhis etmenin en hızlı yolu, doğrulama başarısız olduğunda tam çıktıyı günlüğe kaydetmektir.

Oran sınırlamaları için üssel geri çekilme ekleyin

Oran sınırlaması hataları (429) geçicidir. Doğru yaklaşım, artan gecikmelerle beklemek ve yeniden denemektir — oran sınırı olan herhangi bir API için standart bir uygulama:

import timeimport randomfrom openai import RateLimitError​def complete_with_retry(    messages: list,    model: str = "gpt-5.4-mini",    max_retries: int = 3,    **kwargs) -> dict:    """Retry on rate limits and server errors with exponential backoff."""    last_error = None​    for attempt in range(max_retries):        try:            return safe_complete(messages, model=model, **kwargs)​        except APIStatusError as e:            if e.status_code < 500:                raise  # 4xx: don't retry, request is wrong            last_error = e​        except RateLimitError as e:            last_error = e​        except (APIConnectionError, APITimeoutError) as e:            last_error = e​        if attempt < max_retries - 1:            wait = (2 ** attempt) + random.random()  # jitter prevents thundering herd            logging.warning(f"Attempt {attempt + 1} failed. Waiting {wait:.1f}s before retry.")            time.sleep(wait)​    raise RuntimeError(f"All {max_retries} attempts failed") from last_error

400 veya 401’de yeniden denemeyin — bunlar kendiliğinden düzelmeyecek istemci hatalarıdır.

Görüntü üretimi hatalarını ayıklayın

Görüntü üretimi, standart HTTP hatalarının üzerine kendine özgü başarısızlık modlarına sahiptir:

import base64import requests​def generate_image_safe(prompt: str, model: str = "dall-e-3") -> dict:    """    Generate an image with full error handling.    Returns {"url": str | None, "bytes": bytes | None, "blocked": bool}    """    api_key = os.environ.get("COMETAPI_KEY")    if not api_key:        raise ValueError("COMETAPI_KEY is not set")​    BASE64_MODELS = {"gpt-image-2", "qwen-image"}​    headers = {        "Authorization": f"Bearer {api_key}",        "Content-Type": "application/json"    }​    payload = {"model": model, "prompt": prompt, "size": "1024x1024"}    if model in BASE64_MODELS:        payload["output_format"] = "png"    else:        payload["response_format"] = "url"​    try:        response = requests.post(            "https://api.cometapi.com/v1/images/generations",            json=payload,            headers=headers,            timeout=60        )        response.raise_for_status()    except requests.exceptions.HTTPError as e:        logging.error(f"Image generation HTTP error: {e.response.status_code} {e.response.text}")        raise    except requests.exceptions.Timeout:        logging.error("Image generation timed out after 60s")        raise​    data = response.json().get("data", [])​    if not data:        logging.warning("Image generation returned empty data — prompt may have been filtered.")        return {"url": None, "bytes": None, "blocked": True}​    item = data[0]​    if "revised_prompt" in item:        logging.info(f"Provider revised prompt to: {item['revised_prompt']}")​    if "url" in item:        return {"url": item["url"], "bytes": None, "blocked": False}​    return {        "url": None,        "bytes": base64.b64decode(item["b64_json"]),        "blocked": False    }

Görüntüye özgü dikkat edilmesi gerekenler:

BelirtiNedenÇözüm
Boş data dizisiİstem filtrelendirevised_prompt’u kontrol edin; yeniden ifade edin
GPT Image 2’de response_format hatasıParametre desteklenmiyorBunun yerine output_format kullanın
Qwen Image’da n > 1 hatasıModel kısıtıBunun yerine istekleri döngüye alın
URL daha sonra 403 döndürüyorURL’nin süresi dolduÜretimden hemen sonra indirin

Kaynak**:* CometAPI image generation docs

Video üretimi hatalarını ayıklayın

Video üretimi asenkron olduğu için farklı şekilde başarısız olur. Zaman aşımı hata mesajı her zaman düzgün biçimde olsun diye döngüden önce durum değişkenlerini başlatın:

def submit_and_poll_video(    prompt: str,    model: str = "veo3-fast",    max_wait: int = 600) -> str:    """Submit video task and poll to completion. Returns video URL."""    api_key = os.environ.get("COMETAPI_KEY")    if not api_key:        raise ValueError("COMETAPI_KEY is not set")​    headers = {"Authorization": f"Bearer {api_key}"}​    try:        response = requests.post(            "https://api.cometapi.com/v1/videos",            headers=headers,            files={                "prompt": (None, prompt),                "model": (None, model),                "size": (None, "16x9")            },            timeout=30        )        response.raise_for_status()    except requests.exceptions.HTTPError as e:        logging.error(f"Video submit failed: {e.response.status_code} {e.response.text}")        raise​    task_id = response.json()["id"]    logging.info(f"Video task submitted: {task_id}")​    poll_url = f"https://api.cometapi.com/v1/videos/{task_id}"    elapsed = 0    interval = 10    status = "unknown"   # initialize before loop    progress = 0         # initialize before loop​    while elapsed < max_wait:        try:            poll_response = requests.get(poll_url, headers=headers, timeout=30)            poll_response.raise_for_status()        except requests.exceptions.HTTPError as e:            logging.error(f"Poll request failed: {e.response.status_code}")            raise​        result = poll_response.json()        status = result.get("status", "unknown")        progress = result.get("progress", 0)​        logging.info(f"Task {task_id}: status={status} progress={progress}%")​        if status == "succeeded":            return result["output"][0]        elif status in ("failed", "cancelled"):            error_detail = result.get("error", "no error detail returned")            raise RuntimeError(f"Video task {task_id} failed: {error_detail}")​        time.sleep(interval)        elapsed += interval​    raise TimeoutError(        f"Video task {task_id} did not complete within {max_wait}s. "        f"Last status: {status}, progress: {progress}%"    )

Videoya özgü sorunlar:

BelirtiNedenÇözüm
Görev 10+ dk boyunca queued’da takılıSunucu yüküFarklı bir modelle yeniden deneyin
Herhangi bir hata detayı olmadan failedİstem filtrelendi veya model hatasıİstemi yeniden ifade edin
Video URL’si 403 döndürüyorURL’nin süresi dolduHemen indirin
Runway’de ilk sorguda task_not_existGörev hâlâ başlatılıyor (CometAPI tarafından belgelenmiş davranış)5 sn bekleyip yeniden deneyin
Kling “succeeded” yerine “succeed” döndürürKling’in API’si standart dışı durum dizesi kullanırYoklamada her ikisini de ele alın

Kaynak**:* CometAPI video generation docs**,* Kling Video docs

Node.js sürümü

import OpenAI from 'openai';​const apiKey = process.env.COMETAPI_KEY;if (!apiKey) throw new Error('COMETAPI_KEY is not set');​const client = new OpenAI({  baseURL: 'https://api.cometapi.com/v1',  apiKey,});​async function safeComplete(messages, model = 'gpt-5.4-mini', options = {}) {  let response;​  try {    response = await client.chat.completions.create({ model, messages, ...options });  } catch (err) {    if (err.status && err.status < 500) {      console.error(`Client error ${err.status}: ${err.message}`);    } else {      console.error(`Server/network error: ${err.message}`);    }    throw err;  }​  const choice = response.choices[0];  const finishReason = choice.finish_reason;​  if (finishReason === 'content_filter') {    throw new Error(`Generation blocked by content filter. Model: ${model}`);  }​  if (finishReason === 'length') {    console.warn(`Output truncated. Used ${response.usage?.completion_tokens ?? 'unknown'} tokens.`);  }​  return {    content: choice.message.content ?? '',    finishReason,    toolCalls: choice.message.tool_calls ?? null,  };}​async function completeWithRetry(messages, model = 'gpt-5.4-mini', maxRetries = 3) {  let lastError;​  for (let attempt = 0; attempt < maxRetries; attempt++) {    try {      return await safeComplete(messages, model);    } catch (err) {      // Don't retry 4xx client errors      if (err.status && err.status < 500) throw err;​      lastError = err;      if (attempt < maxRetries - 1) {        const wait = (2 ** attempt + Math.random()) * 1000;        console.warn(`Attempt ${attempt + 1} failed. Retrying in ${(wait / 1000).toFixed(1)}s`);        await new Promise(r => setTimeout(r, wait));      }    }  }​  throw new Error(`All ${maxRetries} attempts failed: ${lastError?.message}`);}​// Usageconst result = await safeComplete(  [{ role: 'user', content: 'Classify as positive/negative/neutral: "Great product!"' }],  'claude-haiku-4-5');​if (result.finishReason === 'tool_calls') {  console.log('Tool call requested:', result.toolCalls);} else {  console.log(result.content);}

Bir hata ayıklama kontrol listesi

Bir üretim başarısız olduğunda ve nereden başlayacağınızdan emin olmadığınızda:

Metin üretimi için:

  • API anahtarı ayarlı mı ve Authorization: Bearer <key> biçiminde mi?
  • finish_reason stop dışında bir şey mi?
  • content null mı? finish_reason tool_calls mı kontrol edin
  • Çıktı kesildi mi? finish_reason: "length" ve usage.completion_tokens’ı kontrol edin
  • Hata 4xx mi (isteği düzeltin) yoksa 5xx mi (yeniden deneyin)?
  • Çıktı uygulama katmanı doğrulamanızdan geçiyor mu? (sessiz başarısızlık)

Görüntü üretimi için:

  • data dizisi boş mu? (içerik filtresi)
  • GPT Image 2’de response_format mi kullandınız? (desteklenmiyor — output_format kullanın)
  • Qwen Image’da n > 1 mi ayarladınız? (desteklenmiyor)
  • URL’nin süresi dolmadan önce görüntüyü indirdiniz mi?

Video üretimi için:

  • Görev queued durumunda mı takıldı? (farklı bir modeli deneyin)
  • Başarısız görev yanıtındaki error alanını kontrol ettiniz mi?
  • Videoyu URL’nin süresi dolmadan önce indirdiniz mi?
  • Hem "succeed" (Kling) hem de "succeeded" (Veo, Runway) durumlarını ele alıyor musunuz?

SSS

S: İsteğim 200 döndürüyor ama içerik yok. Ne oldu?

finish_reason’ı kontrol edin. content_filter ise üretim engellenmiştir — istek başarılı oldu ama çıktı bastırıldı. tool_calls ise model metin yerine bir araç çağırdı ve content tasarım gereği null’dır. finish_reason stop ama içerik yine de boşsa bu bir sessiz başarısızlıktır — tam yanıtı kaydedin ve isteminizi kontrol edin.

S: İstemimin filtrelenip filtrelenmediğini nasıl anlarım?

Metin için: finish_reason === "content_filter"’ı kontrol edin. Görüntü için: data dizisinin boş olup olmadığına bakın. Video için: görev gönderimden kısa süre sonra failed durumuna düşüyor mu ve hata detayı yok mu kontrol edin. Her durumda, istemi daha nötr olacak şekilde yeniden ifade etmeyi deneyin.

S: Başarısız bir isteği ne zaman yeniden denemeliyim?

429 ve 5xx’lerde üssel geri çekilmeyle yeniden deneyin. 4xx’lerde yeniden denemeyin — hatalı bir istek kendiliğinden düzelmez. İstisna, API anahtarlarını döndürüyorsanız 401 olabilir.

S: Üssel geri çekilme nedir ve neden önemlidir?

Hemen yeniden denemek yerine giderek daha uzun beklersiniz: 1 sn, 2 sn, 4 sn. Rasgele titreme (random jitter) eklemek (ör. + random.random()) birden fazla istemcinin aynı anda yeniden denemesini önler. Bu, oran sınırlı her API için standart bir uygulamadır — CometAPI’ye özgü değildir.

S: Video görevi 10 dakika boyunca queued durumunda takılı kaldı. Bu başarısız mı?

Şart değil — yük altında kuyruklar birikebilir. max_wait eşiğinize kadar bekleyin, sonra bir TimeoutError fırlatın ve farklı bir modelle yeniden deneyin. Gerekirse durumu elle kontrol edebilmek için görev kimliğini kaydedin.

S: Sessiz başarısızlıkları nasıl yakalarım?

Sessiz başarısızlıklar uygulama katmanı doğrulaması gerektirir — API çıktının anlamsal olarak yanlış olduğunu söylemez. Çıktının beklenen biçime uyduğunu kontrol edin (geçerli JSON, beklenen etiket, asgari uzunluk). Doğrulama başarısız olduğunda tam çıktıyı kaydedin. En yaygın nedenler belirsiz istemler, yok sayılan biçim talimatları veya görev için çok kısa/çok uzun girdilerdir.

Yapay zeka geliştirme maliyetlerinizi %20 azaltmaya hazır mısınız?

Dakikalar içinde ücretsiz başlayın. Ücretsiz deneme kredileri dahildir. Kredi kartı gerekmez.

Devamını Oku