{"record":{"id":"284327b035c8decb","repo":"Mintplex-Labs/anything-llm","slug":"no-text-to-predict-on","errorCode":null,"errorMessage":"No text to predict on.","messagePattern":"No text to predict on\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"frontend/src/utils/piperTTS/worker.js","lineNumber":141,"sourceCode":"      self.postMessage({ type: \"error\", message: error.message, error }); // Will be an error.\n    });\n}\n\n/**\n * Renders one streamed prediction. Every message posted back carries the\n * streamId so listeners can ignore chunks that belong to a different stream.\n * @param {string} streamId\n * @param {string} text\n */\nasync function runStream(streamId, text) {\n  try {\n    if (ACTIVE_STREAM_ID !== streamId) {\n      // Superseded or aborted while waiting in the queue - never started.\n      self.postMessage({ type: \"stream-end\", streamId, aborted: true });\n      return;\n    }\n    const chunks = splitIntoChunks(text);\n    if (chunks.length === 0) throw new Error(\"No text to predict on.\");\n    self.postMessage({ type: \"stream-start\", streamId, total: chunks.length });\n    for (let i = 0; i < chunks.length; i++) {\n      if (ACTIVE_STREAM_ID !== streamId) break;\n      const audio = await PIPER_SESSION.predict(chunks[i]);\n      if (ACTIVE_STREAM_ID !== streamId) break; // lost ownership mid-predict - drop the stale chunk\n      self.postMessage({\n        type: \"stream-chunk\",\n        streamId,\n        audio,\n        index: i,\n        total: chunks.length,\n      });\n    }\n    self.postMessage({\n      type: \"stream-end\",\n      streamId,\n      aborted: ACTIVE_STREAM_ID !== streamId,\n    });","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/frontend/src/utils/piperTTS/worker.js#L123-L159","documentation":"Thrown inside the Piper TTS Web Worker: runStream splits the submitted text into synthesis chunks, and when splitIntoChunks returns an empty list the stream cannot start, so this Error is raised. It is pure input validation — PIPER_SESSION.predict is never called and no audio work happens. The error propagates through the worker's error handling rather than any HTTP layer.","triggerScenarios":"Enqueueing TTS for an empty or whitespace-only string; text that is entirely stripped away by the chunking logic (e.g. only markdown/symbols, no speakable prose); a UI race where the stream is posted before the message text is set.","commonSituations":"Speaking an empty assistant message; message content that reduces to nothing after sanitization; autoplay/speak-on-arrive features firing on placeholder chunks.","solutions":["Guard at the call site: skip TTS entirely when !text.trim().","Inspect what splitIntoChunks strips — if it removes markdown, make sure real prose remains before posting to the worker.","If queueing from the UI, debounce and ignore empty messages instead of posting them to the worker."],"exampleFix":"// before\nworker.postMessage({ type: 'stream', streamId, text });\n\n// after\nif (!text || !text.trim()) return; // nothing to synthesize\nworker.postMessage({ type: 'stream', streamId, text });","handlingStrategy":"validation","validationCode":"// run before posting a stream to the piperTTS worker\nfunction hasSpeakableText(text) {\n  return typeof text === 'string' && text.trim().length > 0;\n}\nif (!hasSpeakableText(text)) return; // never enqueue empty/whitespace text","typeGuard":"/** @param {any} t @returns {t is string} */\nfunction isSpeakable(t) {\n  return typeof t === 'string' && t.replace(/\\s|[*_`>#-]/g, '').length > 0;\n}","tryCatchPattern":"self.onerror = (e) => {\n  if (/No text to predict on/.test(e.message)) return; // benign — nothing to speak\n  postMessage({ type: 'stream-error', message: e.message });\n};","preventionTips":["Skip TTS for empty or symbol-only messages before posting to the worker.","Debounce speak-on-arrive features so placeholder chunks are never voiced.","Treat this error as benign in worker error handling — logging it loudly just adds noise."],"tags":["piper-tts","web-worker","text-to-speech","input-validation"],"backgroundTag":"empty-input-validation","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}