Start with trial credit

Email and password, key on screen right away.

https://api.uncensoredllmhub.com/v1

Unknown Error From LLM Stream: Causes and Fixes

If you keep seeing unknown error from llm stream learn more, the message almost always hides a specific cause: a wrong base URL, a rate limit, an oversized request or a proxy that buffers events. This page shows how to find which one and fix it.

Updated

Pipe carrying glowing data packets with one broken segment under a magnifier, representing a streaming error

Key points

  • The text comes from the client, so reproduce the call with curl to see the real error body and status.
  • HTTP 429 with code rate_limited or concurrency is the most common cause on a busy account, and a stream keeps its slot until it ends.
  • Check base URL, key, model ID uncensored, body size (8 MB) and total tokens (100,000) before anything else.
  • Retry only 429 and network drops, wait for Retry-After, and keep concurrency under the key limit.

What the message actually tells you

If you searched for unknown error from llm stream learn more, you are probably looking at a toast or a red line in a chat front end, an editor plugin or an agent framework. The wording comes from that client. It means the app asked for a streamed answer, something went wrong before or during the stream, and the app did not know how to describe it. The API itself reports problems with an HTTP status and a JSON error body, and the client has thrown that detail away.

That is good news, because it means you can get the detail back. Send the same request outside the client, read the status line and the body, and the cause is usually obvious within one or two attempts. The rest of this page goes through the causes in the order they tend to occur on this API, then gives you a small streaming client that prints the real error instead of hiding it.

One thing to keep in mind from the start: a streamed request has two failure points. It can fail before the first byte, when the server rejects the request (bad key, bad URL, a limit). Or it can fail in the middle, when the connection drops after some text has already arrived. The fixes differ, so note which of the two you see. If the answer never starts, look at sections two to four. If it starts and then stops, look at the section on proxies and timeouts.

Check the base URL, key and model first

Most stream errors on a fresh setup come from three small mistakes. They take a minute to rule out.

  1. Base URL. It must be https://api.uncensoredllmhub.com/v1, including /v1 and without a trailing /chat/completions. Clients append the path themselves. If you paste the full endpoint into a field that expects a base, the client requests a path that does not exist and reports a vague failure.
  2. Key. The header is Authorization: Bearer YOUR_KEY. A stray space, a newline copied with the key, or a key from another service all fail the same way. Create or copy the key again from the API key page if you are unsure.
  3. Model ID. The only model is uncensored. Clients that offer a dropdown often pre-fill a name from another provider. Type the ID by hand, and call GET /v1/models if you want to confirm what the server lists.

A quick way to test all three at once is the models call. It does not stream, so it separates a connection or key problem from a streaming problem:

curl -i https://api.uncensoredllmhub.com/v1/models   -H "Authorization: Bearer $API_KEY"

If this returns a normal list, the URL and key are fine and you can stop suspecting them. If it fails, fix that before touching anything about streaming. Also check that your account has credit: the API sends your remaining balance in the X-Balance-USD header on responses, which is handy when a key suddenly stops working after heavy use. The pricing page explains top-ups, and new accounts can claim a $0.50 trial from the key page.

Rate limits and the stream that holds its slot

The next most common cause is HTTP 429. There are three flavours, and your client will fold all of them into the same unhelpful message.

SignalMeaningWhat to do
429, code rate_limitedToo many requests per minute for the keySlow down; a full key allows 300 per minute, a trial key 60
429, code concurrencyToo many requests running at onceQueue them; a full key allows 8 at once, a trial key 2
429 with Retry-After: 5Temporary overload on the service sideWait the 5 seconds, then retry

The concurrency limit is the one that surprises people, because of how streaming works. A streamed request occupies its slot until the stream ends, not until the first token arrives. If your app opens a stream for every message and never closes the old one, for example because the user navigated away and the UI forgot to cancel the request, those slots stay taken. On a trial key with a limit of 2, two abandoned streams are enough to make the third message fail.

The symptoms are consistent. The first few messages work, then errors start, then everything works again after a short wait. If that matches, abort streams you no longer need (an AbortController in the browser, closing the response in a server), and cap the number of parallel calls in your own code. Agents are the usual offenders: a planner that fires ten tool calls at once will hit the limit on a trial key immediately.

The response headers help you see where you stand. X-RateLimit-Limit-Requests and X-RateLimit-Limit-Concurrency show the limits that apply to the key you used, and X-Request-Id identifies the call if you need to ask support about it.

Request size and context length

A request can also be refused for being too big. Two numbers matter. The body can be at most 8 MB, and the prompt plus the completion must fit in a 100,000 token context window. Chat front ends that resend the whole conversation on every turn hit these limits slowly and then all at once: the chat works for an hour, then one long message or a pasted file tips it over, and every later turn fails because the history is still in the request.

If the error starts after a long session, test with a short new conversation. If that works, the history is the cause. Trim it by dropping old turns, summarising them into one message, or starting a fresh chat. Large pasted documents are the other trigger. A text file of a few hundred kilobytes is fine, but base64 blobs or very large logs can reach 8 MB faster than you expect.

You do not have to set max_tokens, since the completion can use whatever is left of the window. If you do set it, make sure prompt tokens plus max_tokens stay under 100,000. A client that hard-codes a large max_tokens on top of a long history can push the sum over the window even when the prompt alone looks fine.

Proxies, buffering and timeouts

Streaming uses server-sent events: a long-lived HTTP response that delivers small chunks as they are produced. Anything between you and the API that waits for the whole response before forwarding it will break that. The result is either a long silence followed by a burst, or a timeout and the generic error.

Look for these in your own setup:

  • Reverse proxies. If you route the API through nginx or a similar proxy, turn response buffering off for that location, and raise the read timeout above the longest answer you expect. Long answers from a 100,000 token window can take a while.
  • Corporate or antivirus proxies. Some inspect HTTPS traffic and hold the body. Test from a phone hotspot to rule this out.
  • Serverless functions. Many platforms cap execution time or buffer responses unless you opt in to streaming. If the stream dies at the same number of seconds every time, a platform time limit is the likely cause.
  • Browser extensions and VPNs. Rare, but they can cut idle connections.

The clue that points here is an error in the middle of an answer, with the same cut-off time on every attempt. A rate limit would reject the request at the start, so a mid-stream cut that always happens at, say, 30 seconds is almost never a limit.

A client that shows the real error

Use this when you want the truth rather than the friendly message. It catches the OpenAI SDK exceptions, prints the status and the error body, and reads the retry hint when there is one.

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)

The same idea in Node, with an abort signal so abandoned streams release their slot:

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

And a raw curl call, which removes every client from the picture. -N turns off curl's own buffering and -i prints the status line and headers, including 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."}]}'

If curl streams text fine and your app does not, the API is healthy and the problem sits in the app, its proxy or its settings. If curl shows a 429 or another status, you now have the exact cause.

Retry rules that do not make things worse

Retries help with transient problems and hurt with permanent ones. A short policy keeps you out of trouble.

  • Retry 429 and dropped connections. Wait for Retry-After when it is present, otherwise back off for a few seconds and add some random jitter so parallel workers do not retry in lockstep.
  • Do not retry authentication failures or oversized requests. The result will not change, and each retry only adds noise.
  • Limit attempts to three or four, then show the user the real error text.
  • Cap your own parallelism below the key limit. A semaphore of 6 on a full key leaves room for a second tool using the same key.
  • If a stream breaks halfway, keep the partial text. Resend with that text as an assistant message and ask the model to continue, rather than regenerating from scratch.

Failed or refused requests are not charged, so debugging with repeated test calls does not drain your credit. Successful calls are billed at $0.15 per 1M input tokens and $0.50 per 1M output tokens, and a partial stream that completes normally is simply a short answer. More detail on the request format is in the API documentation.

If you have done all of the above and still see the message, send the X-Request-Id of a failing call to the support page, with the time of the attempt and whether the failure came before or after the first token. That information is enough to trace what happened.

Questions and answers

Why does my app say unknown error from LLM stream without any details?

The wording comes from the client application, which hides the underlying HTTP status. Repeat the request with curl using -i to see the real status and JSON error body.

Is a 429 error a sign the service is down?

Usually not. It means you passed a per-minute or concurrency limit, or the service asked you to wait 5 seconds through Retry-After. Slow down or queue requests and retry.

Why does it work for a few messages and then fail?

Streams hold their concurrency slot until they finish. If earlier streams were never closed, or your history has grown past the context window, later requests fail until the slots free up or the history is trimmed.

Do failed streaming requests cost money?

Failed or refused requests are not charged, so you can test freely. Completed requests are billed by tokens at the normal price.

Your key is one form away

Create an account, copy the key, change the base URL. That is the whole setup.

Get API key

https://api.uncensoredllmhub.com/v1