{"record":{"id":"2eda24c0e07d66f0","repo":"lllyasviel/Fooocus","slug":"an-image-must-be-set-with-set-image-before-m","errorCode":null,"errorMessage":"An image must be set with .set_image(...) before mask prediction.","messagePattern":"An image must be set with \\.set_image\\(\\.\\.\\.\\) before mask prediction\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"extras/sam/predictor.py","lineNumber":146,"sourceCode":"            For ambiguous input prompts (such as a single click), this will often\n            produce better masks than a single prediction. If only a single\n            mask is needed, the model's predicted quality score can be used\n            to select the best mask. For non-ambiguous prompts, such as multiple\n            input prompts, multimask_output=False can give better results.\n          return_logits (bool): If true, returns un-thresholded masks logits\n            instead of a binary mask.\n\n        Returns:\n          (np.ndarray): The output masks in CxHxW format, where C is the\n            number of masks, and (H, W) is the original image size.\n          (np.ndarray): An array of length C containing the model's\n            predictions for the quality of each mask.\n          (np.ndarray): An array of shape CxHxW, where C is the number\n            of masks and H=W=256. These low resolution logits can be passed to\n            a subsequent iteration as mask input.\n        \"\"\"\n        if not self.is_image_set:\n            raise RuntimeError(\"An image must be set with .set_image(...) before mask prediction.\")\n\n        # Transform input prompts\n        coords_torch, labels_torch, box_torch, mask_input_torch = None, None, None, None\n        if point_coords is not None:\n            assert (\n                point_labels is not None\n            ), \"point_labels must be supplied if point_coords is supplied.\"\n            point_coords = self.transform.apply_coords(point_coords, self.original_size)\n            coords_torch = torch.as_tensor(point_coords, dtype=torch.float, device=self.load_device)\n            labels_torch = torch.as_tensor(point_labels, dtype=torch.int, device=self.load_device)\n            coords_torch, labels_torch = coords_torch[None, :, :], labels_torch[None, :]\n        if box is not None:\n            box = self.transform.apply_boxes(box, self.original_size)\n            box_torch = torch.as_tensor(box, dtype=torch.float, device=self.load_device)\n            box_torch = box_torch[None, :]\n        if mask_input is not None:\n            mask_input_torch = torch.as_tensor(mask_input, dtype=torch.float, device=self.load_device)\n            mask_input_torch = mask_input_torch[None, :, :, :]","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/lllyasviel/Fooocus/blob/ae05379cc97bc4361ec8b4ec90193dab21be763f/extras/sam/predictor.py#L128-L164","documentation":"SAM's SamPredictor.predict() requires an input image before decoding prompts, because set_image() precomputes the image embeddings the mask decoder consumes. Calling predict() on a fresh predictor (or after reset_image()) raises RuntimeError. The check is a simple is_image_set flag.","triggerScenarios":"Instantiating SamPredictor and immediately calling predict(point_coords=..., ...) or predict(box=...) without set_image(np_image) first; or calling predict after reset_image() without re-setting an image.","commonSituations":"Reusing one predictor across a batch of images and forgetting set_image between iterations; restructuring inference code so the embedding step is skipped for 'prompt-only' updates; embedding cached offline then attempting to decode with a stateless predictor.","solutions":["Call predictor.set_image(image_rgb) once per image before any predict() calls for that image.","If switching images, call set_image() again (it recomputes features and re-raises is_image_set).","For many prompts on one image, set_image once and loop predict() — that is the intended amortization.","For headless/embedding workflows use SamPredictor with set_image, or the lower-level SamTwoWayTransformer API (ONNX `SamEmbedding`/`SamDecoder` split) instead of skipping set_image."],"exampleFix":"# before\npredictor = SamPredictor(sam)\nmasks, scores, logits = predictor.predict(point_coords=pts, point_labels=lbls)\n\n# after\npredictor = SamPredictor(sam)\npredictor.set_image(image_rgb)  # required first\nmasks, scores, logits = predictor.predict(point_coords=pts, point_labels=lbls)","handlingStrategy":"validation","validationCode":"if not predictor.is_image_set:\n    raise RuntimeError('set_image() must be called before predict()')\n# or simply guard the whole call:\nassert predictor.is_image_set, 'call predictor.set_image(image) first'","typeGuard":"def can_predict(predictor) -> bool:\n    return bool(predictor.is_image_set)","tryCatchPattern":"try:\n    masks, scores, logits = predictor.predict(...)\nexcept RuntimeError as e:\n    if 'set_image' in str(e):\n        predictor.set_image(image_rgb)\n        masks, scores, logits = predictor.predict(...)\n    else:\n        raise","preventionTips":["Encapsulate the lifecycle: one helper per image that does set_image then all predict calls.","Check predictor.is_image_set before predict in loops that may reset state.","Treat reset_image() as making the predictor unusable until the next set_image()."],"tags":["sam","segment-anything","state-machine","runtimeerror"],"backgroundTag":null,"analyzedSha":"ae05379cc97bc4361ec8b4ec90193dab21be763f","analyzedAt":"2026-08-15T04:23:59.533Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}