# Hatalar

Sayfa: https://docs.sonecentral.com/hatalar
Markdown: https://docs.sonecentral.com/hatalar.md

> Hata yanıtının biçimi, bütün hata kodları, hangisinin yeniden denenebileceği ve her birinde ne yapılacağı.

Hatalar OpenAI'nin hata biçimiyle gelir. OpenAI SDK'ları onları kendi hata sınıflarına çevirir.

```json
{
  "error": {
    "message": "Bu tarayıcı anahtarı bu sitede kullanılamaz. Siteyi anahtarın izinli siteleri arasına ekleyin.",
    "type": "permission_error",
    "param": null,
    "code": "origin_not_allowed"
  }
}
```

- `message` Türkçedir ve son kullanıcıya gösterilebilecek kadar sadedir.
- `code` İngilizcedir ve değişmez. Kodunuzda her zaman `code`'a bakın, `message`'a değil.
- `param` hatayı doğuran alanın adıdır, örneğin `model`, `messages`, `input` ya da `after`. İlgili bir alan yoksa `null` olur.

`POST /chat` bu kuralın tek istisnasıdır. Orada gövde JSON değil, düz metindir: `message`'daki Türkçe metnin kendisi. Vercel AI SDK bu metni olduğu gibi `useChat`'in `error.message` değerine koyar. Kod `X-Sone-Error-Code` başlığında gelir; bu başlık tarayıcıdaki koda açılmaz, yalnız sunucudan yapılan isteklerde okunur.

## Kodlar

`x-should-retry` sütununda `false` olan hatalarda aynı isteği yeniden göndermeyin. `Retry-After` sütunu, başlığın taşıdığı bekleme süresidir.

| Durum | `code` | `x-should-retry` | `Retry-After` | Anlamı ve ne yapmalı |
| --- | --- | --- | --- | --- |
| `400` | `invalid_body` | yok | yok | Gövde boş ya da okunamadı. İsteği JSON gövdeyle gönderin. |
| `400` | `invalid_json` | yok | yok | Gövde geçerli JSON değil ya da bir alanın türü yanlış. `message` ayrıntıyı verir. |
| `400` | `missing_user_message` | yok | yok | Son mesaj metin taşıyan bir `user` mesajı değil. Ziyaretçinin yeni mesajını sona koyun. |
| `400` | `invalid_role` | yok | yok | Tanınmayan bir mesaj rolü ya da Responses'ta rolü olmayan bir mesaj öğesi. |
| `400` | `invalid_content` | yok | yok | Bir mesajın içeriği metin ya da parça dizisi değil. |
| `400` | `unsupported_content` | yok | yok | Yeni mesajda görsel, ses ya da dosya var. Yalnız metin gönderin. |
| `400` | `message_too_long` | yok | yok | Yeni bir mesaj 4.000 karakterden uzun. Mesajı kısaltın. |
| `400` | `too_many_new_messages` | yok | yok | Tek istekte 12'den fazla yeni ziyaretçi mesajı var. Asistanın yanıtını geçmişe ekleyip devam edin ya da yeni sohbet başlatın. |
| `400` | `tools_not_supported` | yok | yok | `tools`, `functions` ya da işlev çağrısı öğeleri gönderildi. Asistan işletmenin kendi araçlarını kullanır; bu alanları çıkarın. |
| `400` | `unsupported_parameter` | yok | yok | `n` 1 dışında, `response_format` ya da `text.format` `text` dışında ya da `background: true`. `param` alanın adını verir. |
| `400` | `missing_input` | yok | yok | Responses isteğinde `input` yok. |
| `400` | `invalid_input` | yok | yok | Responses isteğinde `input` bir metin ya da öğe dizisi değil. |
| `400` | `unsupported_item` | yok | yok | Responses isteğinde tanınmayan bir girdi öğesi türü var. |
| `400` | `conflicting_parameters` | yok | yok | `previous_response_id` ile `conversation` birlikte gönderildi. Birini bırakın. |
| `400` | `instructions_too_long` | yok | yok | Responses isteğinde `instructions` 2.000 karakterden ya da JSON olarak 4 KB'tan uzun. |
| `400` | `invalid_metadata` | yok | yok | Responses isteğinde `metadata` sınırı aşıyor: en fazla 16 anahtar, anahtar en fazla 64 karakter, değer en fazla 512 karakterlik metin, tamamı JSON olarak en fazla 4 KB. |
| `400` | `safety_identifier_too_long` | yok | yok | Responses isteğinde `safety_identifier` 64 karakterden uzun. |
| `400` | `user_too_long` | yok | yok | Responses isteğinde `user` 64 karakterden uzun. |
| `400` | `previous_response_id_too_long` | yok | yok | `previous_response_id`, boşlukları atıldıktan sonra bir yanıt kimliğinden uzun. Yanıtın `id` değerini olduğu gibi gönderin. |
| `400` | `item_id_too_long` | yok | yok | Responses isteğinde bir `item_reference` kimliği 64 karakterden uzun. |
| `400` | `conversation_model_mismatch` | `false` | yok | Sohbet başka bir asistanla açılmış. Aynı `model` ile sürdürün ya da yeni sohbet başlatın. |
| `400` | `conversation_full` | `false` | yok | Sohbette 200 ziyaretçi mesajına ulaşıldı. Yeni sohbet başlatın. |
| `400` | `invalid_cursor` | yok | yok | `after` bu sohbete ait bir mesajın kimliği değil. İmleci bırakıp sohbeti baştan okuyun. |
| `400` | `not_cancellable` | yok | yok | `POST /responses/{id}/cancel` çağrıldı. Yanıtlar istek içinde tamamlanır, iptal edilecek iş yoktur. |
| `401` | `missing_api_key` | yok | yok | Anahtar gönderilmedi. |
| `401` | `invalid_api_key` | yok | yok | Anahtar tanınmadı, biçimi bozuk ya da öneki türüyle uyuşmuyor. |
| `401` | `revoked_api_key` | yok | yok | Anahtar iptal edilmiş. Yenisini oluşturun. |
| `402` | `plan_required` | `false` | yok | Çalışma alanının paketi asistan yanıtlarına açık değil. Asistan yanıt vermedi. |
| `403` | `origin_not_allowed` | yok | yok | Tarayıcı anahtarı izin verilen siteler dışından ya da `Origin` başlığı olmadan kullanıldı. Siteyi anahtara ekleyin. |
| `403` | `secret_key_in_browser` | yok | yok | Sunucu anahtarı bir tarayıcıdan kullanıldı. Tarayıcıda tarayıcı anahtarı kullanın. |
| `404` | `model_not_found` | yok | yok | Bu kimlikte, anahtarın çağırabildiği yayında bir asistan yok. `GET /models` kullanılabilenleri listeler. |
| `404` | `conversation_not_found` | yok | yok | Sohbet bu çalışma alanında bir API sohbeti değil ya da anahtarınızın çağıramadığı bir asistanın. Sakladığınız kimliği bırakıp yeni sohbet başlatın. |
| `404` | `previous_response_not_found` | yok | yok | `previous_response_id` ile gösterilen yanıt yok, silinmiş, `store: false` ile üretilmiş ya da anahtarınızın çağıramadığı bir asistanın sohbetinde. |
| `404` | `response_not_found` | yok | yok | Saklanan yanıt yok, silinmiş, 30 günü geçmiş ya da anahtarınızın çağıramadığı bir asistanın sohbetinde. `DELETE /responses/{id}`'de ayrıca: yanıtı başka bir anahtar saklamış. |
| `404` | `file_not_found` | yok | yok | Dosya bağlantısının süresi dolmuş ya da bağlantı bozuk. Sohbetin mesajlarını yeniden okuyup yeni bağlantıyı alın. |
| `409` | `conversation_busy` | yok | 2 | Aynı sohbette önceki mesaj hâlâ yanıtlanıyor; bu mesaj kaydedilmedi. Bekleyip aynı `Idempotency-Key` ile yeniden gönderin. |
| `413` | `request_too_large` | yok | yok | Gövde 1 MB'den büyük. Bütün geçmiş yerine sohbet kimliğini gönderin. |
| `422` | `idempotency_key_reused` | `false` | yok | Aynı `Idempotency-Key` başka bir metinle gönderildi. Her yeni mesajda yeni bir anahtar kullanın. |
| `429` | `rate_limit_exceeded` | yok | Pencereye göre | Anahtarın istek ya da okuma sınırı aşıldı. `Retry-After` kadar bekleyin. |
| `429` | `ai_turn_ceiling` | `false` | 300 | Çalışma alanının API için saatlik ya da günlük otomatik yanıt sınırı, tarayıcı anahtarıyla gelen istekte tarayıcı anahtarlarının payı doldu. Asistan yanıt vermedi. |
| `429` | `assistant_quota_exhausted` | `false` | yok | Sonecentral'ın yapay zekâ kapasitesi şu an dolu. Çalışma alanınızın bir hakkı bitmiş değildir; API yanıtları paketinizden düşmez. Asistan yanıt vermedi: `message` "Asistan şu an yanıt veremiyor." der. |
| `429` | `file_download_limit` | yok | Pencereye göre | Aynı dosya kimliği son bir saatte 10 kez indirildi. `Retry-After` kadar bekleyin. |
| `429` | `file_egress_limit` | yok | UTC gece yarısına kadar | Çalışma alanının günlük dosya indirme sınırı doldu. |
| `503` | `assistant_paused` | Mesaj ekibe ulaştıysa `false` | 60 | Otomatik yanıtlar şu an kapalı. Asistan yanıt vermedi. |
| `503` | `assistant_unavailable` | yok | 30 | Asistan şu an yanıt veremiyor. Bekleyip aynı `Idempotency-Key` ile yeniden gönderin. |
| `503` | `conversation_not_created` | yok | yok | Sohbet açılamadı. Biraz sonra yeniden deneyin. |
| `503` | `message_not_stored` | yok | yok | Mesaj kaydedilemedi. Aynı `Idempotency-Key` ile yeniden deneyin. |
| `503` | `messages_unavailable` | yok | yok | Sohbetin mesajları şu an okunamadı. Sonraki okumada yeniden deneyin. |
| `503` | `file_unavailable` | yok | yok | Dosya şu an indirilemiyor. Biraz sonra yeniden deneyin. |
| `503` | `response_not_deleted` | yok | yok | Saklanan yanıt şu an silinemedi. Biraz sonra yeniden deneyin. |

`Retry-After` saniye cinsindendir ve yukarı yuvarlanır.

Bu kodların dışında iki durum vardır. Aynı adresten dakikada 120'den fazla dosya indirme isteği `429` alır ve bu yanıtın gövdesi OpenAI biçiminde değildir. Beklenmeyen bir sunucu hatasında da gövde bu biçimde olmayabilir; böyle bir `5xx` yanıtını aynı `Idempotency-Key` ile yeniden deneyin.

### Asistan yanıt vermediğinde mesaj nereye gider

`plan_required`, `assistant_quota_exhausted`, `ai_turn_ceiling` ve `assistant_paused` asistanın yanıt veremediğini söyler. Mesajın ne olduğu sohbete bağlıdır:

- **Sohbet zaten açıksa** ziyaretçinin mesajı kaydedilir ve ekibe ulaşır. `message` bunu "Mesajınız ekibe iletildi." diye söyler; `assistant_quota_exhausted`'te "Mesajınız ekibe iletildi, ekipten biri size yanıt verecek." der. Ekibin yanıtı sohbetin mesajlarında gelir: [Asistan yanıt vermediğinde](https://docs.sonecentral.com/insan-devri.md#asistan-yanit-vermediginde).
- **Yeni bir sohbet açılacaksa** hiçbir şey kaydedilmez ve sohbet açılmaz. `message` "Biraz sonra yeniden deneyin." der.

`assistant_unavailable` da iki türlü gelir. Asistan tura hiç başlayamadıysa hiçbir şey olmamıştır ve `message` "Biraz sonra yeniden deneyin." der. Tur başlayıp yarıda kaldıysa ziyaretçinin mesajı kaydedilmiştir ve `message` "Mesajınız ekibe iletildi." der; aynı anahtarla yeniden gönderirseniz mesaj ikinci kez kaydedilmez, asistan onu yanıtlar.

## `type` değerleri

| `type` | Hangi hatalarda |
| --- | --- |
| `invalid_request_error` | `400`, `404`, `409`, `413` ve `422` |
| `authentication_error` | `401` |
| `permission_error` | `403` |
| `insufficient_quota` | `402` `plan_required` ve `429` `assistant_quota_exhausted` |
| `rate_limit_error` | `429` `rate_limit_exceeded`, `ai_turn_ceiling`, `file_download_limit` ve `file_egress_limit` |
| `server_error` | `503` |

## Yanıt başlıkları

| Başlık | Ne işe yarar |
| --- | --- |
| `x-request-id` | İsteğin kimliği, her yanıtta gelir. Destek isterken bunu paylaşın. |
| `retry-after` | Kaç saniye sonra yeniden deneyebileceğiniz. |
| `x-should-retry` | `false` gelirse aynı isteği yeniden göndermeyin. OpenAI SDK'ları buna kendiliğinden uyar. |
| `x-sone-conversation-id` | Sohbetin kimliği. Bir tur yanıtında gelir; akışta, akış başlarken. |
| `x-sone-error-code` | Yalnız `POST /chat` hatalarında: hatanın kodu. Tarayıcıdaki koda açılmaz. |

Tarayıcıdaki kodunuz `x-request-id`, `retry-after`, `x-should-retry` ve `x-sone-conversation-id` başlıklarını okuyabilir.

## Yeniden denemek

- `x-should-retry: false` gelirse yeniden denemeyin; aynı istek aynı sonucu alır. Bu başlık `plan_required`, `assistant_quota_exhausted`, `ai_turn_ceiling`, `idempotency_key_reused`, `conversation_model_mismatch` ve `conversation_full` ile, mesaj ekibe ulaştıysa `assistant_paused` ile de gelir.
- `Retry-After` başlığı varsa ve `x-should-retry: false` yoksa o kadar bekleyip yeniden deneyin. `rate_limit_exceeded`, `conversation_busy`, `assistant_paused`, `assistant_unavailable`, `file_download_limit` ve `file_egress_limit` bu başlığı taşır. `ai_turn_ceiling` de taşır ama yeniden denemeyin.
- `Retry-After` taşımayan `503` yanıtlarında ve ağ hatalarında aynı isteği aynı `Idempotency-Key` başlığıyla yeniden gönderin. Artan aralıklarla bekleyin: önce 1, sonra 2, 4 ve 8 saniye. Sonecentral aynı mesajı ikinci kez kaydetmez. Örnek ve tarayıcı anahtarındaki tek istisna: [Tekrar denemek](https://docs.sonecentral.com/sohbet-surekliligi.md#tekrar-denemek).
- `conversation_busy` bir yarış durumudur: aynı sohbete aynı anda iki mesaj gitti. Arayüzünüzde bir tur bitmeden yenisini göndermeyin.
- Geri kalan `4xx` hatalarında yeniden denemek işe yaramaz; isteği düzeltin.

OpenAI SDK'ları `408`, `409`, `429` ve `5xx` yanıtlarını varsayılan olarak iki kez kendiliğinden yeniden dener. `x-should-retry` başlığına uyar; `retry-after` en fazla 60 saniyeyse o kadar bekler. `Idempotency-Key` başlığını ise kendileri eklemez; isteğin seçeneklerinde siz verin: [Chat Completions](https://docs.sonecentral.com/chat-completions.md#tekrar-denemek).

## Akış sırasında hata

`"stream": true` gönderseniz de anahtar, sınır, asistan, sohbet ve paket kontrolleri akış başlamadan yapılır. Bu kontrollerden geçmeyen istek yukarıdaki gibi sıradan bir HTTP hatası alır. Akış başladıktan sonra bir hata olursa HTTP durumu artık değişemez. Bu durumda akışa bir hata yazılır ve akış kapanır:

- **Chat Completions:** `data: {"error": {…}}` parçası, yukarıdaki `error` nesnesiyle; ardından `data: [DONE]`. OpenAI SDK'ları bunu hata olarak fırlatır.
- **Responses:** önce `type`, `code`, `message`, `param` ve `sequence_number` taşıyan bir `error` olayı, ardından `response.failed`. `response.failed` olayındaki yanıtın `status` değeri `failed` olur, `error` alanı aynı `code` ve `message`'ı taşır. `[DONE]` gelmez. OpenAI'nin Node SDK'sı `error` olayında `APIError` fırlatır, kod `error.code`'dadır; Python SDK'sı onu `type` değeri `"error"` olan bir olay olarak verir.
- **Vercel AI SDK:** `{"type":"error","errorText":"…"}` parçası, ardından `data: [DONE]`. `useChat`'in `status` değeri `error` olur ve `error.message` bu metni taşır.

Akış başladıktan sonra gelebilecek hatalar `ai_turn_ceiling`, sınır tur sırasında dolarsa, ve tur yarıda kalırsa `assistant_unavailable`'dır. Hata gelmeden önce gönderilen mesajlar sohbete kaydedilmiştir. Onları `GET /conversations/{id}/messages` ile okuyabilirsiniz.

## Kullanıcıya ne gösterilir

`message` alanı ziyaretçiye gösterilebilir ama çoğu zaman daha iyisi, ziyaretçinin yapabileceği bir şeyi söylemektir. Örneğin `429` ve `503` için "Şu an yanıt veremiyoruz, birazdan yeniden deneyin." Açık bir sohbette `ai_turn_ceiling`, `assistant_quota_exhausted`, `plan_required` ya da `assistant_paused` geldiyse mesaj ekibe ulaşmıştır: "Mesajınız ekibimize ulaştı, en kısa sürede buradan yanıt vereceğiz." Hata kodlarını ziyaretçiye göstermeyin.
