jamiepine/voicebox · error · ValueError

Rewrite needs non-empty text to restate.

Error message

Rewrite needs non-empty text to restate.

What it means

Raised by rewrite_as_profile after collapse_repetitive_artifacts(user_text) produces an empty string (personality.py:105-107). The personality guard already passed; the input text was either empty, whitespace, or reduced to nothing by the artifact-collapser (e.g. input was only stutter/repetition that got collapsed away). This protects the LLM from a no-op prompt.

Source

Thrown at backend/services/personality.py:107

        prompt="Speak.",
        system=system_prompt,
        max_tokens=256,
        temperature=0.9,
        model_size=resolved_size,
    )
    return PersonalityResult(text=output.strip(), model_size=resolved_size)


async def rewrite_as_profile(
    personality: str | None,
    user_text: str,
    model_size: str | None = None,
) -> PersonalityResult:
    """Restate the user's text in the character's voice, ideas intact."""
    character = _require_personality(personality)
    cleaned = collapse_repetitive_artifacts(user_text)
    if not cleaned.strip():
        raise ValueError("Rewrite needs non-empty text to restate.")

    backend = llm_service.get_llm_model()
    resolved_size = model_size or backend.model_size

    system_prompt = _build_system_prompt(character, _REWRITE_TASK)
    output = await backend.generate(
        prompt=cleaned,
        system=system_prompt,
        max_tokens=1024,
        temperature=0.3,
        model_size=resolved_size,
    )
    return PersonalityResult(text=output.strip(), model_size=resolved_size)

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Validate non-empty text client-side before enabling the submit button.
  2. Pass the original (pre-collapse) text length to the guard, or trim whitespace before sending.
  3. If using the API directly, ensure the text field has at least one non-whitespace, non-repetition character.
  4. Adjust collapse_repetitive_artifacts if it is over-aggressively eating legitimate short inputs.

Example fix

// before
const text = textarea.value; // may be whitespace
await api.post('/generate', {text, personality: true});
// after
const text = textarea.value.trim();
if (!text) return;
await api.post('/generate', {text, personality: true});
Defensive patterns

Strategy: validation

Validate before calling

def rewrite_input_ok(user_text: str) -> bool:
    return bool(user_text and user_text.strip())

# before rewrite:
if not rewrite_input_ok(user_text):
    raise HTTPException(400, 'Text to rewrite must be non-empty.')

Type guard

def is_rewritable_text(s: object) -> bool:
    return isinstance(s, str) and bool(s.strip())

Try / catch

try:
    result = await rewrite_as_profile(personality, user_text)
except ValueError as e:
    if str(e) == 'Rewrite needs non-empty text to restate.':
        raise HTTPException(400, str(e))
    raise HTTPException(400, str(e))

Prevention

When it happens

Trigger: POST /generate with personality=true and an empty text field; input was only whitespace or repeated characters ('....', 'aaaa'); input was only emoji or punctuation that collapse_repetitive_artifacts strips.

Common situations: Frontend allows submitting an empty textarea; paste glitch produced whitespace-only text; user typed only a character repetition that the collapser eats.

Related errors


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