rohitg00/ai-engineering-from-scratch · error · ValueError

reusable_file_id must not be empty

Error message

reusable_file_id must not be empty

What it means

Raised by build_multimodal_request when reusable_file_id is empty or whitespace-only. The builder attaches a reusable file asset by id; an empty id cannot reference anything and would silently drop the document context from the request (multimodal_lab_fixture).

Source

Thrown at certifications/claude/lessons/08-messages-api-and-application-lifecycle/code/main.py:200


def stable_cache_key(model: str, stable_prefix: str) -> str:
    payload = f"{model}\0{stable_prefix}".encode("utf-8")
    return hashlib.sha256(payload).hexdigest()


IMAGE_MEDIA_TYPES = {"image/jpeg", "image/png", "image/gif", "image/webp"}
DOCUMENT_MEDIA_TYPES = {"application/pdf", "text/plain"}


def build_multimodal_request(prompt: str, image_bytes: bytes, reusable_file_id: str) -> dict[str, Any]:
    """Build an offline request body with inline vision and a reusable file asset."""
    if not prompt.strip():
        raise ValueError("prompt must not be empty")
    if not image_bytes:
        raise ValueError("image_bytes must not be empty")
    if not reusable_file_id.strip():
        raise ValueError("reusable_file_id must not be empty")
    return {
        "model": "<current-model-id>",
        "max_tokens": 400,
        "messages": [
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": "image/png",
                            "data": base64.b64encode(image_bytes).decode("ascii"),
                        },
                    },
                    {
                        "type": "document",

View on GitHub (pinned to 39ea8a1c6d)

Solutions

  1. Pass the id returned by a successful file upload
  2. Check the upload response for the id field before building the request
  3. Default ids to a sentinel in fixtures and assert they were replaced

Example fix

# before
file_id = ""
if upload_ok:
    file_id = resp["id"]
build_multimodal_request(prompt, img, file_id)
# after
if not upload_ok:
    raise ValueError("upload failed")
build_multimodal_request(prompt, img, resp["id"])
Defensive patterns

Strategy: validation

Validate before calling

if not reusable_file_id or not reusable_file_id.strip():
    raise ValueError("file upload did not return an id")
req = build_multimodal_request(prompt, image_bytes, reusable_file_id)

Type guard

def is_file_id(value: object) -> bool:
    return isinstance(value, str) and bool(value.strip())

Prevention

When it happens

Trigger: Calling build_multimodal_request('prompt', image_bytes, '') or ' ' when an upload step failed and its id variable was never set.

Common situations: A file-upload call failed silently and left the id unset, string formatting of the id produced an empty value, or fixture placeholders not filled in.

Related errors


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/a4cc10c5f3b063df. Report an issue: GitHub.