{"record":{"id":"8cb679dbfbbce6d7","repo":"BerriAI/litellm","slug":"unsupported-image-input-plain-string-values-that","errorCode":null,"errorMessage":"Unsupported image input: plain string values that are not URLs are not accepted. Provide image bytes or a file-like object.","messagePattern":"Unsupported image input: plain string values that are not URLs are not accepted\\. Provide image bytes or a file-like object\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/black_forest_labs/image_edit/transformation.py","lineNumber":212,"sourceCode":"        max_depth: int = DEFAULT_MAX_RECURSE_DEPTH,\n    ) -> bytes:\n        \"\"\"Read image bytes from various input types.\"\"\"\n        if depth > max_depth:\n            raise ValueError(\n                f\"Max recursion depth {max_depth} reached while reading image bytes for Black Forest Labs image edit.\"\n            )\n        if isinstance(image, bytes):\n            return image\n        elif isinstance(image, list):\n            # If it's a list, take the first image\n            return self._read_image_bytes(image[0], depth=depth + 1, max_depth=max_depth)\n        elif isinstance(image, str):\n            if image.startswith((\"http://\", \"https://\")):\n                response: Final = safe_get(litellm.module_level_client, image, timeout=60.0)\n                response.raise_for_status()\n                return response.content\n            else:\n                raise ValueError(\n                    \"Unsupported image input: plain string values that are not URLs are not accepted. \"\n                    \"Provide image bytes or a file-like object.\"\n                )\n        elif hasattr(image, \"read\"):\n            # File-like object\n            pos: Final = getattr(image, \"tell\", lambda: 0)()\n            if hasattr(image, \"seek\"):\n                image.seek(0)\n            data: Final = image.read()\n            if hasattr(image, \"seek\"):\n                image.seek(pos)\n            return data\n        else:\n            raise ValueError(\n                f\"Unsupported image type: {type(image)}. Expected bytes, str (URL or file path), or file-like object.\"\n            )\n\n    def transform_image_edit_request(","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/black_forest_labs/image_edit/transformation.py#L194-L230","documentation":"When the image argument is a plain string, _read_image_bytes only accepts strings starting with http:// or https:// (it fetches them with a 60s GET). Any other string — including local file paths, base64 data, or arbitrary text — raises ValueError telling you to supply bytes or a file-like object. Despite the message mentioning 'file path' in the sibling branch's error, this path branch does not read the filesystem.","triggerScenarios":"Passing image=\"/tmp/photo.png\", image=\"data:image/png;base64,...\", or any non-URL string to image_edit on a black_forest_labs model.","commonSituations":"Assuming local paths are supported because the other error message mentions them; passing base64-encoded bytes as a string instead of raw bytes; generating images to disk then feeding the path back for editing.","solutions":["Read local files into bytes first: image=open(path,'rb').read() or pass the open file object (it is seek-rewound automatically).","For base64 strings, decode first: image=base64.b64decode(s).","Host the image and pass its https URL.","If you want path support, wrap it yourself: image=Path(p).read_bytes()."],"exampleFix":"# before\nlitellm.image_edit(model=..., image=\"/tmp/photo.png\", prompt=\"...\")\n\n# after\nwith open(\"/tmp/photo.png\", \"rb\") as f:\n    litellm.image_edit(model=..., image=f, prompt=\"...\")","handlingStrategy":"type-guard","validationCode":"def to_image_arg(image):\n    if isinstance(image, str):\n        if image.startswith((\"http://\", \"https://\")):\n            return image\n        return open(image, \"rb\").read()  # treat as local path\n    return image\n\nimage = to_image_arg(image)","typeGuard":"def is_usable_bfl_image_str(s: str) -> bool:\n    return s.startswith((\"http://\", \"https://\"))","tryCatchPattern":"null","preventionTips":["Normalize inputs at your boundary: strings must be URLs; everything else becomes bytes or a file object.","Decode base64 strings with base64.b64decode before passing.","Lint for string literals passed as image that lack the http(s) scheme."],"tags":["bfl","image-input","validation","file-path","base64"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}