{"record":{"id":"293753d1f488d609","repo":"lllyasviel/Fooocus","slug":"unknown-type-self-type-please-choose-from-nu","errorCode":null,"errorMessage":"Unknown type: {self.type}. Please choose from: 'numpy', 'pil', 'filepath'.","messagePattern":"Unknown type: (.+?)\\. Please choose from: 'numpy', 'pil', 'filepath'\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"modules/gradio_hijack.py","lineNumber":253,"sourceCode":"    def _format_image(\n        self, im: _Image.Image | None\n    ) -> np.ndarray | _Image.Image | str | None:\n        \"\"\"Helper method to format an image based on self.type\"\"\"\n        if im is None:\n            return im\n        fmt = im.format\n        if self.type == \"pil\":\n            return im\n        elif self.type == \"numpy\":\n            return np.array(im)\n        elif self.type == \"filepath\":\n            path = self.pil_to_temp_file(\n                im, dir=self.DEFAULT_TEMP_DIR, format=fmt or \"png\"\n            )\n            self.temp_files.add(path)\n            return path\n        else:\n            raise ValueError(\n                \"Unknown type: \"\n                + str(self.type)\n                + \". Please choose from: 'numpy', 'pil', 'filepath'.\"\n            )\n\n    def preprocess(\n        self, x: str | dict[str, str]\n    ) -> np.ndarray | _Image.Image | str | dict | None:\n        \"\"\"\n        Parameters:\n            x: base64 url data, or (if tool == \"sketch\") a dict of image and mask base64 url data\n        Returns:\n            image in requested format, or (if tool == \"sketch\") a dict of image and mask in requested format\n        \"\"\"\n        if x is None:\n            return x\n\n        mask = None","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/lllyasviel/Fooocus/blob/ae05379cc97bc4361ec8b4ec90193dab21be763f/modules/gradio_hijack.py#L235-L271","documentation":"postprocess() of the vendored gradio Image converts the model output back to a UI value according to self.type; only 'pil', 'numpy', and 'filepath' have branches, and anything else falls to else and raises ValueError. This is the runtime echo of the constructor's type check — it means self.type was changed after construction or bypassed it.","triggerScenarios":"Mutating img.type = 'tensor' (or 'cv2', 'str') on a live component between construction and the callback returning; subclassing and skipping __init__ validation; deserializing a saved component config with a foreign type.","commonSituations":"Custom tabs that dynamically reconfigure components; deepcopy/pickle round-trips of UI state that carry an old or edited type field.","solutions":["Never assign to .type after construction — rebuild the component with the desired type.","If you must support an extra format, subclass postprocess and add the branch before the else.","Re-run the constructor validation invariant: keep self.type within {'numpy','pil','filepath'} at all times."],"exampleFix":"# before\nimg.type = 'tensor'\n# after\nimg = Image(type='numpy')  # rebuild with supported type","handlingStrategy":"type-guard","validationCode":"assert img.type in ('numpy', 'pil', 'filepath'), f'Image.type corrupted: {img.type!r}'","typeGuard":"def has_valid_image_type(component) -> bool:\n    return getattr(component, 'type', None) in ('numpy', 'pil', 'filepath')","tryCatchPattern":null,"preventionTips":["Never mutate .type post-construction; rebuild the component instead.","If subclassing gr.Image, re-run the type validation in __init__."],"tags":["gradio","ui","postprocess","state-mutation"],"backgroundTag":null,"analyzedSha":"ae05379cc97bc4361ec8b4ec90193dab21be763f","analyzedAt":"2026-08-15T04:23:59.533Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}