Belangrijkste punten
- De tekst komt van de client, dus reproduceer de call met curl om de echte foutbody en status te zien.
- HTTP 429 met code rate_limited of concurrency is de meest voorkomende oorzaak op een druk account, en een stream houdt zijn slot vast tot het einde.
- Controleer base URL, sleutel, model ID uncensored, body-grootte (8 MB) en totale tokens (100.000) voordat je iets anders doet.
- Herhaal alleen 429 en netwerkonderbrekingen, wacht op Retry-After en houd het aantal gelijktijdige verzoeken onder de limiet per sleutel.
Wat de melding je eigenlijk vertelt
Als je zocht naar onbekende fout tijdens LLM-streaming, kijk je waarschijnlijk naar een toast of een rode regel in een chatfrontend, een editorplugin of een agentframework. De tekst komt van die client. Het betekent dat de app om een gestreamd antwoord vroeg, er iets misging voor of tijdens de stream, en de app niet wist hoe het het moest beschrijven. De API zelf meldt problemen met een HTTP-status en een JSON-foutbody, en de client heeft die details weggegooid.
Dat is goed nieuws, want dan kun je de details terugkrijgen. Stuur hetzelfde verzoek buiten de client om, lees de statusregel en de body, en de oorzaak is meestal binnen een of twee pogingen duidelijk. De rest van deze pagina gaat door de oorzaken in de volgorde waarin ze op deze API voorkomen, en geeft je een kleine streamingclient die de echte fout afdrukt in plaats van deze te verbergen.
Houd vanaf het begin rekening met één ding: een gestreamd verzoek heeft twee faalpunten. Het kan falen voordat het eerste byte arriveert, wanneer de server het verzoek afwijst (verkeerde sleutel, verkeerde URL, een limit). Of het kan falen in het midden, wanneer de verbinding breekt nadat er al wat tekst is aangekomen. De oplossingen verschillen, dus noteer welke van de twee je ziet. Als het antwoord nooit begint, bekijk dan de secties twee tot en met vier. Als het begint en dan stopt, bekijk dan de sectie over proxies en time-outs.
Controleer eerst de base URL, sleutel en model
De meeste streamfouten bij een frisse setup komen door drie kleine fouten. Ze zijn binnen een minuut uitgesloten.
- Base URL. Deze moet
https://api.uncensoredllmhub.com/v1zijn, inclusief/v1en zonder een trailing/chat/completions. Clients voegen het pad zelf toe. Als je het volledige endpoint in een veld plakt dat een base verwacht, vraagt de client een pad op dat niet bestaat en rapporteert een vaag falen. - Sleutel. De header is
Authorization: Bearer YOUR_KEY. Een losse spatie, een regeleinde dat met de sleutel wordt gekopieerd, of een sleutel van een andere service falen allemaal op dezelfde manier. Maak of kopieer de sleutel opnieuw van de API-sleutelpagina als je twijfelt. - Model ID. Het enige model is
uncensored. Clients die een dropdown aanbieden vullen vaak een naam van een andere provider voor. Typ de ID handmatig en roepGET /v1/modelsaan als je wilt bevestigen wat de server opsomt.
Een snelle manier om alle drie tegelijk te testen is de aanroep van de models. Deze streamt niet, dus het scheidt een verbindings- of sleutelprobleem van een streamingprobleem:
curl -i https://api.uncensoredllmhub.com/v1/models -H "Authorization: Bearer $API_KEY"
Als dit een normale lijst retourneert, zijn de URL en de sleutel in orde en kun je stoppen met het verdenken van die onderdelen. Als het mislukt, los dat op voordat je iets doet met streaming. Controleer ook of je account tegoed heeft: de API stuwt je resterende saldo mee in de X-Balance-USD-header van de respons, wat handig is als een sleutel plotseling stopt na zwaar gebruik. De prijzenpagina legt uit hoe je tegoed kunt opwaarderen, en nieuwe accounts kunnen $0,50 proeftegoed claimen op de sleutelpagina.
Rate limits en de stream die zijn slot vasthoudt
De volgende meest voorkomende oorzaak is HTTP 429. Er zijn drie varianten, en je client vouwt ze allemaal samen in dezelfde onhulpzame boodschap.
| Signaal | Betekenis | Wat te doen |
|---|---|---|
429, code rate_limited | Te veel verzoeken per minuut voor de sleutel | Vertraag; een volledige sleutel staat 300 per minuut toe, een proefsleutel 60 |
429, code concurrency | Te veel gelijktijdige verzoeken | Zet ze in een wachtrij; een volledige sleutel staat 8 tegelijk toe, een proefsleutel 2 |
429 met Retry-After: 5 | Tijdelijke overbelasting aan de servicekant | Wacht de 5 seconden, en probeer het opnieuw |
De limiet voor gelijktijdige verzoeken is degene die mensen verrast, vanwege hoe streaming werkt. Een gestreamd verzoek bezet zijn slot tot de stream eindigt, niet tot het eerste token arriveert. Als je app een stream opent voor elk bericht en de oude nooit sluit, bijvoorbeeld omdat de gebruiker weg navigeert en de UI vergeten is het verzoek te annuleren, blijven die slots bezet. Op een proefsleutel met een limiet van 2 zijn twee verlaten streams genoeg om het derde bericht te laten falen.
De symptomen zijn consistent. De eerste paar berichten werken, dan beginnen de fouten, en daarna werkt alles weer na een korte wachttijd. Als dat overeenkomt, onderbreek streams die je niet meer nodig hebt (een AbortController in de browser, het sluiten van de respons op een server), en beperk het aantal gelijktijdige calls in je eigen code. Agents zijn de gebruikelijke boosdoeners: een planner die tien toolaanroepen tegelijk afvuurt, raakt direct de limiet op een proefsleutel.
De responsheaders helpen je om te zien waar je staat. X-RateLimit-Limit-Requests en X-RateLimit-Limit-Concurrency tonen de limieten die gelden voor de gebruikte sleutel, en X-Request-Id identificeert de aanroep als je het ondersteuning moet vragen.
Verzoekgrootte en contextlengte
Een verzoek kan ook worden geweigerd omdat het te groot is. Twee getallen zijn belangrijk. De body mag maximaal 8 MB zijn, en de prompt plus de completion moeten passen in een contextvenster van 100.000 tokens. Chatfrontends die het hele gesprek bij elke beurt opnieuw verzenden, raken deze limieten langzaam en dan ineens: de chat werkt een uur lang, dan knapt een lang bericht of een geplakt bestand het door, en elke latere beurt faalt omdat de geschiedenis nog steeds in het verzoek zit.
Als de fout begint na een lange sessie, test dan met een kort nieuw gesprek. Als dat werkt, is de geschiedenis de oorzaak. Knip hem bij door oude beurten te verwijderen, ze samen te vatten tot één bericht, of een nieuwe chat te starten. Grote geplakte documenten zijn de andere trigger. Een tekstbestand van een paar honderd kilobyte is prima, maar base64-blobs of zeer grote logs kunnen sneller 8 MB bereiken dan je verwacht.
Je hoeft max_tokens niet in te stellen, omdat de completion het resterende deel van het contextvenster kan gebruiken. Als je het wel instelt, zorg er dan voor dat prompt-tokens plus max_tokens onder de 100.000 blijven. Een client die een grote max_tokens hard-codeert bovenop een lange geschiedenis, kan de som over het venster duwen, zelfs als de prompt op zich nog goed lijkt.
Proxies, buffering en time-outs
Streaming gebruikt server-sent events: een langlevende HTTP-response die kleine chunks levert zodra ze worden geproduceerd. Alles tussen jou en de API dat wacht op de hele response voordat het doorstuurt, breekt dat. Het resultaat is ofwel lange stilte gevolgd door een burst, of een time-out en de algemene fout.
Zoek naar deze in je eigen setup:
- Reverse proxies. Als je de API door een nginx of een vergelijkbare proxy routeert, schakel dan response buffering uit voor die locatie, en verhoog de read-timeout boven de langste antwoord die je verwacht. Lange antwoorden uit een contextvenster van 100.000 tokens kunnen even duren.
- Bedrijfs- of antivirusproxies. Sommige inspecteren HTTPS-verkeer en houden de body vast. Test vanaf een telefoonhotspot om dit uit te sluiten.
- Serverless-functies. Veel platformen begrenzen de uitvoertijd of bufferen responsen tenzij je kiest voor streaming. Als de stream steeds op hetzelfde aantal seconden stopt, is een platform-tijdslimiet de waarschijnlijke oorzaak.
- Browserextensies en VPN's. Zeldzaam, maar ze kunnen idle-verbindingen verbreken.
De aanwijzing die hierheen wijst, is een fout in het midden van een antwoord, met dezelfde cutoff-tijd bij elke poging. Een rate limit zou het verzoek aan het begin afwijzen, dus een mid-stream cutoff die altijd gebeurt op bijvoorbeeld 30 seconden is bijna nooit een limit.
Een client die de echte fout toont
Gebruik dit als je de waarheid wilt in plaats van de vriendelijke melding. Het vangt de OpenAI SDK-uitzonderingen, drukt de status en de foutbody af, en leest de retry-aanwijzing als die er is.
import time
from openai import OpenAI, APIConnectionError, APIStatusError, RateLimitError
client = OpenAI(
base_url="https://api.uncensoredllmhub.com/v1",
api_key="YOUR_API_KEY",
)
def stream_once(messages):
stream = client.chat.completions.create(
model="uncensored",
messages=messages,
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if getattr(chunk, "usage", None):
print("\n[usage]", chunk.usage)
messages = [{"role": "user", "content": "Write two sentences about harbours."}]
for attempt in range(4):
try:
stream_once(messages)
break
except RateLimitError as e:
wait = int(e.response.headers.get("retry-after", 5))
print("429:", e.body, "- waiting", wait, "s")
time.sleep(wait)
except APIStatusError as e:
print("status", e.status_code, e.body)
print("request id:", e.response.headers.get("x-request-id"))
break
except APIConnectionError as e:
print("connection problem:", e)
time.sleep(2)
Hetzelfde idee in Node, met een abort-signal zodat verlaten streams hun slot vrijgeven:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.uncensoredllmhub.com/v1",
apiKey: process.env.API_KEY,
});
const controller = new AbortController();
try {
const stream = await client.chat.completions.create(
{
model: "uncensored",
messages: [{ role: "user", content: "Write two sentences about harbours." }],
stream: true,
},
{ signal: controller.signal }
);
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
} catch (err) {
console.error("status:", err.status, "body:", err.error);
}
// call controller.abort() when the user leaves the page
En een ruwe curl-call, waardoor elke client uit het beeld verdwijnt. -N schakelt curl's eigen buffering uit en -i print de statusregel en headers, inclusief X-Request-Id:
curl -N -i https://api.uncensoredllmhub.com/v1/chat/completions -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -d '{"model":"uncensored","stream":true,"messages":[{"role":"user","content":"Say hello."}]}'
Als curl tekst goed streamt en je app niet, is de API gezond en zit het probleem in de app, zijn proxy of zijn instellingen. Als curl een 429 of een andere status toont, heb je nu de exacte oorzaak.
Retry-regels die dingen niet erger maken
Retries helpen bij tijdelijke problemen en schaden bij permanente. Een kort beleid houdt je uit de problemen.
- Herhaal 429 en verbroken verbindingen. Wacht op
Retry-Afterals die aanwezig is, anders wacht je een paar seconden en voeg je willekeurige jitter toe zodat parallelle workers niet in unisono herhalen. - Herhaal geen authenticatiefouten of te grote verzoeken. Het resultaat verandert niet, en elke retry voegt alleen ruis toe.
- Beperk pogingen tot drie of vier, en toon daarna de echte fouttekst aan de gebruiker.
- Beperk je eigen parallelisme onder het sleutellimit. Een semaphore van 6 op een volledige sleutel laat ruimte voor een tweede tool die dezelfde sleutel gebruikt.
- Als een stream halverwege breekt, bewaar de gedeeltelijke tekst. Stuur opnieuw met die tekst als een assistant bericht en vraag het model om door te gaan, in plaats van opnieuw te genereren vanaf het begin.
Mislukte of geweigerde verzoeken worden niet in rekening gebracht, dus debuggen met herhaalde testverzoeken put je tegoed niet uit. Succesvolle verzoeken worden gefactureerd tegen $0,15 per 1M input tokens en $0,50 per 1M output tokens, en een gedeeltelijke streaming die normaal eindigt is gewoon een kort antwoord. Meer details over het verzoekformaat vind je in de API-documentatie.
Als je alles hierboven hebt gedaan en het bericht nog steeds ziet, stuur dan de X-Request-Id van een mislukte call naar de supportpagina, samen met het tijdstip van de poging en of de fout optrad voor of na de eerste token. Deze informatie is voldoende om te traceren wat er gebeurde.
