{"record":{"id":"45b391bc82e1efc4","repo":"zylon-ai/private-gpt","slug":"empty-response-from-mistral-tokenizer","errorCode":null,"errorMessage":"Empty response from Mistral tokenizer","messagePattern":"Empty response from Mistral tokenizer","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/llm/tokenizers/mistral.py","lineNumber":662,"sourceCode":"\n        request: Any = ChatCompletionRequest(\n            messages=messages,  # type: ignore[arg-type]\n            tools=[Tool(**tool) for tool in tools] if tools else None,\n        )\n\n        # Apply pydantic workaround\n        maybe_serialize_tool_calls(request)\n        truncate_tool_call_ids(request)\n\n        encoded = self.mistral.encode_chat_completion(request)\n\n        if tokenize:\n            tokens: list[int] = encoded.tokens\n            return tokens\n        else:\n            result = cast(str | None, encoded.text)\n            if not result:\n                raise ValueError(\"Empty response from Mistral tokenizer\")\n            return result\n\n    def decode(\n        self,\n        ids: list[int] | int,\n        skip_special_tokens: bool = True,\n    ) -> str:\n        \"\"\"Decode token IDs to text.\"\"\"\n        if isinstance(ids, int):\n            ids = [ids]\n\n        if not skip_special_tokens:\n            SpecialTokenPolicy = _load_mistral_module(\n                \"mistral_common.tokens.tokenizers.base\"\n            ).SpecialTokenPolicy\n\n            return cast(str, self.tokenizer.decode(ids, SpecialTokenPolicy.KEEP))\n","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/llm/tokenizers/mistral.py#L644-L680","documentation":"In apply_chat_template with tokenize=False, the wrapper returns encoded.text from mistral_common's encode_chat_completion. If the encoding produced None or an empty string — which should not happen for a valid request — it raises ValueError('Empty response from Mistral tokenizer') to avoid returning a falsy prompt.","triggerScenarios":"Calling the mistral tokenizer's apply_chat_template(..., tokenize=False) on a request whose encoded form has no text: malformed/degenerate message lists (e.g. empty messages, content stripped to nothing after normalization) or version drift in mistral_common changing encode output.","commonSituations":"Edge-case inputs such as empty conversation arrays; messages whose content is removed by normalization (reasoning stripped, tool-call content empty); mismatches between the wrapper's request building and the installed mistral-common version.","solutions":["Inspect the request passed to encode_chat_completion: verify messages are non-empty and have non-empty content after normalization.","Pin mistral-common to the version validated by the project (reinstall via uv sync --inexact --extra llm-mistral).","Reproduce with tokenize=True to see whether the encoding itself works, narrowing the issue to text rendering."],"exampleFix":"# before\nprompt = tok.apply_chat_template([], tokenize=False)  # degenerate input\n\n# after\nassert messages and all(m.get('content') for m in messages if m['role'] != 'tool')\nprompt = tok.apply_chat_template(messages, tokenize=False)","handlingStrategy":"try-catch","validationCode":"def prompt_input_ok(messages) -> bool:\n    return bool(messages) and any(\n        m.get('role') in ('user', 'system', 'assistant', 'tool') and (m.get('content') or m.get('tool_calls'))\n        for m in messages\n    )","typeGuard":null,"tryCatchPattern":"try:\n    prompt = tok.apply_chat_template(messages, tokenize=False)\nexcept ValueError as e:\n    if 'Empty response' in str(e):\n        logger.error('degenerate encode for messages=%r', messages)\n        raise BadPromptError('conversation produced empty template output') from e\n    raise","preventionTips":["Reject empty conversations and empty-content messages before calling apply_chat_template.","Keep mistral-common pinned; re-test after upgrades.","When debugging, call with tokenize=True to isolate whether encoding or text rendering failed."],"tags":["mistral","tokenizer","empty-response","edge-case"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}