Jev Troubleshooting: Common Errors and Proven Fixes

Updated Applies to Jev 1.13

Every Jev integration hits the same handful of failures, and almost all of them have short fixes. This guide is the reference: a symptom-to-fix table for HTTP errors, a section on the JSON parsing traps that account for most “the API is broken” reports, and what to do when confidence values look off. Work through it top to bottom and you will resolve the vast majority of issues without filing anything.

TL;DR: 401 means the key; 404 means the model slug; 429 means slow down and back off; parse failures mean the message content was not JSON-loaded; weird confidence usually means a vague question. Check the table below before anything else, and confirm the exact model slug on the OpenRouter model page first — it is the most common culprit.

HTTP errors: symptom, cause, fix

ErrorLikely causeFix
401 UnauthorizedKey missing from environment, misread variable, or revoked keyPrint the variable in the same shell as the call; re-create the key on OpenRouter if needed; confirm the Bearer prefix is present
404 / unknown modelWrong or outdated model slugConfirm the exact model slug on the OpenRouter model page (typesafe/jev-1.13 is the listing at the time of writing; slugs change with versions) and resend
429 Too Many RequestsRate limit or spend cap hitExponential backoff with jitter; check per-key limits and credit balance; batch or throttle concurrent calls
400 Bad RequestMalformed JSON body or missing required fieldValidate the body parses as JSON locally; check the OpenAI-compatible field names (model, messages)
5xx server errorsUpstream issue on the channelRetry with backoff up to 2–3 times, then queue and alert; do not hammer

A minimal retry wrapper covers 429 and 5xx behavior in one place:

import json, os, time, requests

def ask_jev_with_retry(prompt: str, max_retries: int = 3) -> dict:
    # Confirm the exact model slug on the OpenRouter model page
    for attempt in range(max_retries):
        resp = requests.post(
            "https://openrouter.ai/api/v1/chat/completions",
            headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"},
            json={
                "model": "typesafe/jev-1.13",
                "messages": [{"role": "user", "content": prompt}],
            },
            timeout=30,
        )
        if resp.status_code == 200:
            return json.loads(resp.json()["choices"][0]["message"]["content"])
        if resp.status_code in (429, 500, 502, 503):
            time.sleep(2 ** attempt)  # exponential backoff
            continue
        resp.raise_for_status()  # 401/404/400 will raise here with context
    raise RuntimeError("Jev call failed after retries")

The wrapper returns the fixture-shaped answer on success; the response shape shown is an example fixture and official field names should be confirmed in the official documentation. For the official TypeSafe AI channel’s own error codes and retry guidance, follow the official documentation at typesafe.ai.

Parse failures: the usual suspects

These account for most “the API is broken” reports that turn out to be client-side:

  1. Treating content as a dict. The message content is a JSON string. resp.json()["choices"][0]["message"]["content"] gives you a string; json.loads it before accessing answer or confidence.
  2. Assuming the envelope is the answer. answer lives inside the parsed content, not at the top level of the HTTP response. The HTTP envelope is OpenAI-compatible; the judgment payload is inside it — example fixture, confirm exact field names in the official documentation:
{
  "answer": "billing",
  "confidence": 0.94,
  "rationale": "The message disputes a charge amount rather than reporting a bug."
}
  1. No defense against a malformed payload. Rare, but wrap the parse and retry once before paging anyone:
try:
    result = json.loads(resp.json()["choices"][0]["message"]["content"])
except (json.JSONDecodeError, KeyError):
    result = ask_jev_with_retry(prompt)  # one retry, then alert

The retry returns a fresh fixture-shaped answer; the shape shown is an example fixture and official field names should be confirmed in the official documentation.

Confidence anomalies

When confidence looks wrong, work down this list:

If none of these move the needle, isolate one input and run it through the first-call tutorial’s minimal request — most residual issues turn out to be state accidentally included in the prompt. The product FAQ scoring case shows a full pipeline where these checks run automatically.

This guide applies to Jev 1.13.

Frequently asked questions

Why do I get a 404 when calling Jev?

Almost always a wrong or outdated model slug. Check the OpenRouter model page for the current id — slugs change with versions — and resend with the exact value.

The API returns 200 but my code fails parsing. Why?

The message content is a JSON string, not an object. Parse it with a JSON loader, and handle the rare malformed payload with one retry before alerting.

Confidence scores look wrong — all high or all low. What now?

First check that the question states its type and boundaries clearly; drifting confidence usually reflects drifting inputs, not a model fault. Then review the question-design guidance.

Keep reading