{"record":{"id":"01dc5c8efdff8f42","repo":"chenhg5/cc-connect","slug":"text-exceeds-max-text-len-d-d","errorCode":null,"errorMessage":"text exceeds max_text_len (%d > %d)","messagePattern":"text exceeds max_text_len \\((.+?) > (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/engine.go","lineNumber":15875,"sourceCode":"\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}\n\tslog.Info(\"tts: synthesis successful\", \"format\", format, \"audio_size\", len(audioData))\n\tif err := as.SendAudio(e.ctx, replyCtx, audioData, format); err != nil {\n\t\treturn fmt.Errorf(\"send audio: %w\", err)","sourceCodeStart":15857,"sourceCodeEnd":15893,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L15857-L15893","documentation":"When TTS is configured, synthesizeAndSendTTS enforces an optional per-request text length limit: if tts.max_text_len > 0 and the reply text has more runes than that limit, synthesis is refused with this error naming both the actual and maximum rune counts.","triggerScenarios":"Requesting a voice reply for text whose UTF-8 rune count exceeds tts.max_text_len, e.g. asking the agent to speak a long code answer when max_text_len = 500.","commonSituations":"Long agent responses sent as voice; conservative max_text_len values set to control provider cost; multilingual text where users underestimate rune counts.","solutions":["Increase tts.max_text_len in config.toml (or remove it to disable the cap) and reload","Truncate or summarize the text to fit within max_text_len before requesting TTS","Send the long content as a text/file message instead of voice"],"exampleFix":"// before (config.toml)\n[tts]\nenabled = true\nmax_text_len = 200\n// after\n[tts]\nenabled = true\nmax_text_len = 2000","handlingStrategy":"fallback","validationCode":"if e.TTSMaxTextLen() > 0 && utf8.RuneCountInString(text) > e.TTSMaxTextLen() {\n    text = truncateRunes(text, e.TTSMaxTextLen())\n}","typeGuard":null,"tryCatchPattern":"if err := e.SynthesizeAndSendTTS(p, replyCtx, text); err != nil {\n    if strings.Contains(err.Error(), \"exceeds max_text_len\") {\n        p.Reply(replyCtx, text) // send as text instead\n        return\n    }\n    return err\n}","preventionTips":["Truncate or summarize long replies before requesting voice synthesis","Set max_text_len generously or omit it to lift the cap","Use rune counts (utf8.RuneCountInString), not byte length, when pre-checking","Watch for repeated failures with long agent outputs and switch those to text replies"],"tags":["tts","limit","text-length"],"backgroundTag":"payload-too-large","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"}