{"record":{"id":"5a9b4e3225108bbd","repo":"rohitg00/ai-engineering-from-scratch","slug":"prompt-must-not-be-empty","errorCode":null,"errorMessage":"prompt must not be empty","messagePattern":"prompt must not be empty","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"certifications/claude/lessons/08-messages-api-and-application-lifecycle/code/main.py","lineNumber":196,"sourceCode":"def batch(items: list[Any], size: int) -> list[list[Any]]:\n    if size < 1:\n        raise ValueError(\"batch size must be positive\")\n    return [items[index : index + size] for index in range(0, len(items), size)]\n\n\ndef stable_cache_key(model: str, stable_prefix: str) -> str:\n    payload = f\"{model}\\0{stable_prefix}\".encode(\"utf-8\")\n    return hashlib.sha256(payload).hexdigest()\n\n\nIMAGE_MEDIA_TYPES = {\"image/jpeg\", \"image/png\", \"image/gif\", \"image/webp\"}\nDOCUMENT_MEDIA_TYPES = {\"application/pdf\", \"text/plain\"}\n\n\ndef build_multimodal_request(prompt: str, image_bytes: bytes, reusable_file_id: str) -> dict[str, Any]:\n    \"\"\"Build an offline request body with inline vision and a reusable file asset.\"\"\"\n    if not prompt.strip():\n        raise ValueError(\"prompt must not be empty\")\n    if not image_bytes:\n        raise ValueError(\"image_bytes must not be empty\")\n    if not reusable_file_id.strip():\n        raise ValueError(\"reusable_file_id must not be empty\")\n    return {\n        \"model\": \"<current-model-id>\",\n        \"max_tokens\": 400,\n        \"messages\": [\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\"type\": \"text\", \"text\": prompt},\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\n                            \"type\": \"base64\",\n                            \"media_type\": \"image/png\",\n                            \"data\": base64.b64encode(image_bytes).decode(\"ascii\"),","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/certifications/claude/lessons/08-messages-api-and-application-lifecycle/code/main.py#L178-L214","documentation":"Raised by build_multimodal_request when prompt is empty or whitespace-only. The offline request builder refuses to construct a Messages API body with no user instruction, since such a request cannot express intent and would be rejected upstream anyway (multimodal_lab_fixture).","triggerScenarios":"Calling build_multimodal_request('', image_bytes, 'file_1') or with a prompt of only spaces/tabs.","commonSituations":"Passing an unvalidated form field, a prompt template rendering to an empty string when a variable is missing, or a test fixture placeholder left blank.","solutions":["Supply a non-empty prompt describing what to do with the image","Validate prompt at the UI/form boundary before calling the builder","In templates, fail loudly when an interpolated prompt variable is empty"],"exampleFix":"# before\nbuild_multimodal_request(\"\", img, \"file_1\")\n# after\nbuild_multimodal_request(\"Describe this screenshot\", img, \"file_1\")","handlingStrategy":"validation","validationCode":"if not prompt or not prompt.strip():\n    raise ValueError(\"prompt required\")\nreq = build_multimodal_request(prompt.strip(), image_bytes, file_id)","typeGuard":"def is_usable_prompt(prompt: object) -> bool:\n    return isinstance(prompt, str) and bool(prompt.strip())","tryCatchPattern":null,"preventionTips":["Validate prompts at the form/API boundary","Assert interpolated template variables are non-empty before rendering"],"tags":["vision","multimodal","argument-validation","python"],"backgroundTag":"empty-prompt-rejected","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}