chenhg5/cc-connect · error
tts is not configured
Error message
tts is not configured
What it means
Engine.synthesizeAndSendTTS guards TTS synthesis: if the Engine has no TTS config at all (e.tts is nil) or the [tts] section exists but is disabled (Enabled=false), voice synthesis cannot proceed and this error is returned instead of generating audio.
Source
Thrown at core/engine.go:15869
chunks = append(chunks, string(runes[:end]))
runes = runes[end:]
}
return chunks
}
// sendTTSReply synthesizes fullResponse text and sends audio to the platform.
// Called asynchronously after EventResult; text reply is always sent first.
func (e *Engine) sendTTSReply(p Platform, replyCtx any, text string) {
slog.Debug("tts: sendTTSReply called", "platform", p.Name(), "text_len", len(text))
if err := e.synthesizeAndSendTTS(p, replyCtx, text); err != nil {
slog.Error("tts: voice reply failed", "platform", p.Name(), "error", err)
}
}
func (e *Engine) synthesizeAndSendTTS(p Platform, replyCtx any, text string) error {
if e.tts == nil || !e.tts.Enabled {
return fmt.Errorf("tts is not configured")
}
if e.tts.TTS == nil {
return fmt.Errorf("tts provider is not configured")
}
if e.tts.MaxTextLen > 0 && utf8.RuneCountInString(text) > e.tts.MaxTextLen {
return fmt.Errorf("text exceeds max_text_len (%d > %d)", utf8.RuneCountInString(text), e.tts.MaxTextLen)
}
as, ok := p.(AudioSender)
if !ok {
return fmt.Errorf("platform %s does not support audio sending", p.Name())
}
slog.Info("tts: starting synthesis", "voice", e.tts.Voice, "speed", e.tts.Speed, "text_len", len(text))
opts := TTSSynthesisOpts{
Voice: e.tts.Voice,
LanguageType: e.tts.LanguageType,
Speed: e.tts.Speed,
}
audioData, format, err := e.tts.TTS.Synthesize(e.ctx, StripMarkdown(text), opts)View on GitHub (pinned to 4000b2338a)
Solutions
- Add a [tts] section with enabled = true and a valid provider configuration in config.toml
- Configure the TTS provider (credentials, voice, etc.) and restart the daemon
- Use a text reply instead of voice if TTS is intentionally disabled
- Guard the command handler with a TTS-enabled check and tell the user how to enable it
Example fix
// before (config.toml) # no tts section // after (config.toml) [tts] enabled = true provider = "feishu" voice = "default"
Defensive patterns
Strategy: fallback
Validate before calling
if cfg.TTS == nil || !cfg.TTS.Enabled {
reply("voice replies are disabled; add [tts] enabled=true to config.toml")
return
} Type guard
func ttsAvailable(e *core.Engine) bool { return e != nil && e.TTSConfig() != nil && e.TTSConfig().Enabled } Try / catch
if err := e.SynthesizeAndSendTTS(p, replyCtx, text); err != nil {
if strings.Contains(err.Error(), "tts is not configured") {
slog.Warn("tts disabled, falling back to text reply")
p.Reply(replyCtx, text)
return
}
slog.Error("tts failed", "err", err)
} Prevention
- Include a [tts] section in config.toml if voice replies are desired
- Run the doctor/health check to verify TTS is configured at startup
- Add a startup log warning when voice commands exist but TTS is disabled
- Document the TTS config keys for operators
When it happens
Trigger: Triggering a voice/TTS reply (e.g. a voice-reply command or voice output of a response) when no [tts] block is present in config.toml, or when tts.enabled = false.
Common situations: Users upgrading cc-connect and expecting voice replies without adding the [tts] config section; configs where TTS was intentionally disabled but a voice command is still issued; copying a config that omits TTS settings.
Related errors
- tts provider is not configured
- pico2wave: voice=%s text=%q: %w, output: %s
- acp: agent option "cmd" or "command" is required (path or na
- acp: command %q not found in PATH: %w
- claudecode: project dir not found
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/2c49c9ac5c0e94df.
Report an issue: GitHub.