{"record":{"id":"40388062a6bb22a5","repo":"chenhg5/cc-connect","slug":"tts-provider-is-not-configured","errorCode":null,"errorMessage":"tts provider is not configured","messagePattern":"tts provider is not configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/engine.go","lineNumber":15872,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"synthesize: %w\", err)\n\t}","sourceCodeStart":15854,"sourceCodeEnd":15890,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L15854-L15890","documentation":"Engine.synthesizeAndSendTTS distinguishes between TTS being enabled and an actual provider backend being attached. If e.tts.Enabled is true but e.tts.TTS (the provider implementation) is nil, synthesis cannot run and this error is thrown.","triggerScenarios":"Config with [tts] enabled = true but a missing/invalid provider configuration so no provider instance was constructed; or programmatic use where the engine was given a TTSConfig without a TTS provider implementation.","commonSituations":"Partial config migration where the enabled flag was set but provider credentials (e.g. app_id/app_secret for the speech API) were never filled in; a build excluding the TTS provider plugin so registration never happens.","solutions":["Complete the provider configuration under [tts] (credentials, voice) and restart","Verify the provider plugin is compiled in (rebuild without the relevant no_* build tag)","Check startup logs for provider initialization failures; fix the underlying init error","In code, ensure the provider is assigned to e.tts.TTS before calling synthesizeAndSendTTS"],"exampleFix":"// before\n[tts]\nenabled = true\n# provider credentials missing\n// after\n[tts]\nenabled = true\nprovider = \"feishu\"\napp_id = \"cli_xxx\"\napp_secret = \"...\"","handlingStrategy":"fallback","validationCode":"if ttsCfg.Enabled && ttsProvider == nil {\n    return errors.New(\"tts enabled but provider missing; check [tts] provider credentials\")\n}","typeGuard":null,"tryCatchPattern":"if err := e.SynthesizeAndSendTTS(p, replyCtx, text); err != nil {\n    if strings.Contains(err.Error(), \"provider is not configured\") {\n        slog.Error(\"tts provider missing; check provider plugin compiled in and credentials set\")\n        p.Reply(replyCtx, text) // fallback to text\n        return\n    }\n    return err\n}","preventionTips":["Verify at startup that a TTS provider instance is registered whenever [tts].enabled = true","Rebuild with the provider plugin included (check no_* build tags)","Keep provider credentials in config.toml or env and validate them on boot","Log provider initialization errors clearly so partial configs are caught early"],"tags":["tts","configuration","provider"],"backgroundTag":"missing-dependency","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}