sipeed/picoclaw · warning
text is required
Error message
text is required
What it means
Returned by tts.SynthesizeAndStore when text is empty after strings.TrimSpace. Synthesis of blank input is meaningless, so the provider call is skipped. Typically the upstream LLM produced an empty or whitespace-only reply that was passed through unfiltered.
Source
Thrown at pkg/audio/tts/tts.go:108
ctx context.Context,
provider TTSProvider,
store media.MediaStore,
text string,
filename string,
channel string,
chatID string,
) (string, error) {
if provider == nil {
return "", fmt.Errorf("tts provider is not configured")
}
if store == nil {
return "", fmt.Errorf("media store not configured")
}
if channel == "" || chatID == "" {
return "", fmt.Errorf("no target channel/chat available")
}
if strings.TrimSpace(text) == "" {
return "", fmt.Errorf("text is required")
}
stream, err := provider.Synthesize(ctx, text)
if err != nil {
return "", fmt.Errorf("tts synthesize failed: %w", err)
}
defer stream.Close()
err = os.MkdirAll(media.TempDir(), 0o700)
if err != nil {
return "", fmt.Errorf("failed to create media temp dir: %w", err)
}
fileExt := ".ogg"
contentType := "audio/ogg"
if provider.Name() == "mimo-tts" {
fileExt = ".mp3"
contentType = "audio/mpeg"View on GitHub (pinned to 49183d7e8d)
Solutions
- Filter empty/whitespace text before calling SynthesizeAndStore
- When the model may answer non-verbally, fall back to a default phrase or skip voice output
- Trim input early and log when synthesis is skipped
Example fix
// before
ref, err := tts.SynthesizeAndStore(ctx, p, s, reply, name, ch, id)
// after
if strings.TrimSpace(reply) == `` {
return ``, nil // nothing to say
}
ref, err := tts.SynthesizeAndStore(ctx, p, s, reply, name, ch, id) Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(text) == `` {
return nil // nothing to synthesize; skip gracefully
} Type guard
func isTextRequired(err error) bool {
return err != nil && err.Error() == `text is required`
} Try / catch
if err != nil && isTextRequired(err) {
// upstream produced no speakable text: skip voice output, optionally log
} Prevention
- Trim and check model replies before entering the TTS pipeline
- Handle non-verbal model answers (tool calls, images) with a default phrase or silence
- Never pass raw unvalidated LLM output to SynthesizeAndStore
When it happens
Trigger: The model's answer is '' or only spaces/newlines (e.g. it replied entirely via a tool call or image); the user typed only whitespace; the text was trimmed/consumed earlier by mistake.
Common situations: Voice-reply pipelines piping raw model output into TTS; edge-case prompts that yield empty completions.
Related errors
- no target channel/chat available
- token cannot be empty
- ${label} must be a JSON object.
- ${label}.${key} must be a string.
- Enter and confirm the new login password.
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/2ccc3c58b6567b42.
Report an issue: GitHub.