jamiepine/voicebox · warning · HTTPException

Each example must be a [user, assistant] pair

Error message

Each example must be a [user, assistant] pair

What it means

Returned by POST /llm/generate when request.examples contains an inner list whose length is not exactly 2. examples is typed Optional[List[List[str]]] with max_length=8; the schema guarantees a list-of-lists-of-strings but cannot enforce the inner arity, so this route-level check enforces the [user, assistant] pair contract before the pairs are zipped into chat turns.

Source

Thrown at backend/routes/llm.py:60

                task_manager.error_download(progress_model_name, str(e))

        task_manager.start_download(progress_model_name)
        create_background_task(download_llm_background())

        return JSONResponse(
            status_code=202,
            content={
                "message": f"Qwen3 {model_size} is being downloaded. Please wait and try again.",
                "model_name": progress_model_name,
                "downloading": True,
            },
        )

    examples: list[tuple[str, str]] | None = None
    if request.examples:
        for pair in request.examples:
            if len(pair) != 2:
                raise HTTPException(
                    status_code=400,
                    detail="Each example must be a [user, assistant] pair",
                )
        examples = [(pair[0], pair[1]) for pair in request.examples]

    try:
        text = await backend.generate(
            prompt=request.prompt,
            system=request.system,
            max_tokens=request.max_tokens,
            temperature=request.temperature,
            model_size=model_size,
            examples=examples,
        )
        return models.LLMGenerateResponse(text=text, model_size=model_size)
    except Exception as e:
        # The backend exception text can include filesystem paths and stack
        # frames — log it server-side and hand the client a generic message.

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Ensure every entry in examples is exactly [userText, assistantText] — two non-empty strings.
  2. Validate the shape on the client before sending: pairs.every(p => Array.isArray(p) && p.length === 2).
  3. If you need richer few-shot metadata (labels, tags), keep it out of examples — those pairs map directly onto chat messages.
  4. Reduce examples to <=8 pairs to also satisfy the max_length constraint on the field.

Example fix

// before
body: {prompt, examples: [['q','a','why']]}
// after
body: {prompt, examples: [['q','a']]}
Defensive patterns

Strategy: validation

Validate before calling

function validateExamples(ex?: string[][]) {
  if (!ex) return undefined;
  if (ex.length > 8) throw new Error('At most 8 example pairs');
  for (const p of ex) {
    if (!Array.isArray(p) || p.length !== 2 || typeof p[0] !== 'string' || typeof p[1] !== 'string') {
      throw new Error('Each example must be a [user, assistant] pair');
    }
  }
  return ex as [string, string][];
}

Type guard

type ChatPair = [string, string];
function isChatPair(p: unknown): p is ChatPair {
  return Array.isArray(p) && p.length === 2 && p.every(v => typeof v === 'string');
}
const isExamples = (x: unknown): x is ChatPair[] =>
  Array.isArray(x) && x.length <= 8 && x.every(isChatPair);

Try / catch

if (payload.examples && !isExamples(payload.examples)) {
  // surface inline error in the UI; do not send
} else {
  await fetch('/llm/generate', {method:'POST', body: JSON.stringify(payload)});
}

Prevention

When it happens

Trigger: POST /llm/generate with examples like [["u1","a1","extra"]] (3 elements), [["only-user"]] (1 element), or [[]] (0 elements). A single malformed pair aborts the whole request before generation.

Common situations: Refinement service assembled a triple by mistake (user, assistant, rationale); client serialized a single string instead of a pair; prompt template builder emitted an empty placeholder pair; JSON edit left a dangling comma producing a 3-element array.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/e1d74fef3b5bb738. Report an issue: GitHub.