{"record":{"id":"2c49c9ac5c0e94df","repo":"chenhg5/cc-connect","slug":"tts-is-not-configured","errorCode":null,"errorMessage":"tts is not configured","messagePattern":"tts is not configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/engine.go","lineNumber":15869,"sourceCode":"\n\t\tchunks = append(chunks, string(runes[:end]))\n\t\trunes = runes[end:]\n\t}\n\treturn chunks\n}\n\n// sendTTSReply synthesizes fullResponse text and sends audio to the platform.\n// Called asynchronously after EventResult; text reply is always sent first.\nfunc (e *Engine) sendTTSReply(p Platform, replyCtx any, text string) {\n\tslog.Debug(\"tts: sendTTSReply called\", \"platform\", p.Name(), \"text_len\", len(text))\n\tif err := e.synthesizeAndSendTTS(p, replyCtx, text); err != nil {\n\t\tslog.Error(\"tts: voice reply failed\", \"platform\", p.Name(), \"error\", err)\n\t}\n}\n\nfunc (e *Engine) synthesizeAndSendTTS(p Platform, replyCtx any, text string) error {\n\tif e.tts == nil || !e.tts.Enabled {\n\t\treturn fmt.Errorf(\"tts is not configured\")\n\t}\n\tif e.tts.TTS == nil {\n\t\treturn fmt.Errorf(\"tts provider is not configured\")\n\t}\n\tif e.tts.MaxTextLen > 0 && utf8.RuneCountInString(text) > e.tts.MaxTextLen {\n\t\treturn fmt.Errorf(\"text exceeds max_text_len (%d > %d)\", utf8.RuneCountInString(text), e.tts.MaxTextLen)\n\t}\n\tas, ok := p.(AudioSender)\n\tif !ok {\n\t\treturn fmt.Errorf(\"platform %s does not support audio sending\", p.Name())\n\t}\n\tslog.Info(\"tts: starting synthesis\", \"voice\", e.tts.Voice, \"speed\", e.tts.Speed, \"text_len\", len(text))\n\topts := TTSSynthesisOpts{\n\t\tVoice:        e.tts.Voice,\n\t\tLanguageType: e.tts.LanguageType,\n\t\tSpeed:        e.tts.Speed,\n\t}\n\taudioData, format, err := e.tts.TTS.Synthesize(e.ctx, StripMarkdown(text), opts)","sourceCodeStart":15851,"sourceCodeEnd":15887,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L15851-L15887","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (config.toml)\n# no tts section\n// after (config.toml)\n[tts]\nenabled = true\nprovider = \"feishu\"\nvoice = \"default\"","handlingStrategy":"fallback","validationCode":"if cfg.TTS == nil || !cfg.TTS.Enabled {\n    reply(\"voice replies are disabled; add [tts] enabled=true to config.toml\")\n    return\n}","typeGuard":"func ttsAvailable(e *core.Engine) bool { return e != nil && e.TTSConfig() != nil && e.TTSConfig().Enabled }","tryCatchPattern":"if err := e.SynthesizeAndSendTTS(p, replyCtx, text); err != nil {\n    if strings.Contains(err.Error(), \"tts is not configured\") {\n        slog.Warn(\"tts disabled, falling back to text reply\")\n        p.Reply(replyCtx, text)\n        return\n    }\n    slog.Error(\"tts failed\", \"err\", err)\n}","preventionTips":["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"],"tags":["tts","configuration","voice"],"backgroundTag":"feature-not-enabled","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}