lllyasviel/Fooocus · error · Exception
**** ERROR: Saving image outside the output folder is not al
Error message
**** ERROR: Saving image outside the output folder is not allowed.
What it means
save_image's timestamped-filename helper (ldm_patched/utils/path_utils.py) refuses to write outside the designated output folder: it joins output_dir with the subfolder taken from filename_prefix and verifies via os.path.commonpath that the resolved path is still inside output_dir. If filename_prefix contains '..' segments (or an absolute-path trick) that escapes, it prints a diagnostic and raises a bare Exception. This is a path-traversal guard for image saving.
Source
Thrown at ldm_patched/utils/path_utils.py:253
def compute_vars(input, image_width, image_height):
input = input.replace("%width%", str(image_width))
input = input.replace("%height%", str(image_height))
return input
filename_prefix = compute_vars(filename_prefix, image_width, image_height)
subfolder = os.path.dirname(os.path.normpath(filename_prefix))
filename = os.path.basename(os.path.normpath(filename_prefix))
full_output_folder = os.path.join(output_dir, subfolder)
if os.path.commonpath((output_dir, os.path.abspath(full_output_folder))) != output_dir:
err = "**** ERROR: Saving image outside the output folder is not allowed." + \
"\n full_output_folder: " + os.path.abspath(full_output_folder) + \
"\n output_dir: " + output_dir + \
"\n commonpath: " + os.path.commonpath((output_dir, os.path.abspath(full_output_folder)))
print(err)
raise Exception(err)
try:
counter = max(filter(lambda a: a[1][:-1] == filename and a[1][-1] == "_", map(map_filename, os.listdir(full_output_folder))))[0] + 1
except ValueError:
counter = 1
except FileNotFoundError:
os.makedirs(full_output_folder, exist_ok=True)
counter = 1
return full_output_folder, filename, counter, subfolder, filename_prefix
View on GitHub (pinned to ae05379cc9)
Solutions
- Strip traversal segments from the prefix: keep only os.path.basename components, or normalize and reject '..' before calling save_image.
- Pass a plain filename (e.g. 'Fooocus/img_001') and let the function build the subfolder under output_dir.
- Read the printed diagnostic (it shows full_output_folder vs output_dir vs commonpath) to see exactly which prefix component escaped.
Example fix
# before
save_image(images, output_dir, '../../shared/img', ...)
# after
prefix = os.path.basename('../../shared/img') # -> 'img'
save_image(images, output_dir, prefix, ...) Defensive patterns
Strategy: validation
Validate before calling
import os
safe = not os.path.isabs(filename_prefix) and '..' not in os.path.normpath(filename_prefix).split(os.sep)
if not safe:
filename_prefix = os.path.basename(filename_prefix)
# strongest guarantee: resolved target must stay under output_dir
target = os.path.abspath(os.path.join(output_dir, os.path.dirname(os.path.normpath(filename_prefix))))
assert os.path.commonpath((output_dir, target)) == output_dir Type guard
def is_safe_prefix(output_dir: str, prefix: str) -> bool:
p = os.path.normpath(prefix)
if os.path.isabs(p) or p.startswith('..'):
return False
target = os.path.abspath(os.path.join(output_dir, p))
return os.path.commonpath((output_dir, target)) == output_dir Try / catch
try:
save_image(img, output_dir, prefix, ...)
except Exception as e:
if 'outside the output folder' in str(e):
prefix = os.path.basename(prefix) # retry with sanitized prefix
save_image(img, output_dir, prefix, ...)
else:
raise Prevention
- Treat any caller-supplied filename_prefix as untrusted: whitelist [A-Za-z0-9_./-] and drop '..' segments.
- Prefer bare filenames/subfolder names like 'Fooocus/run_01' and let the util construct the full path.
When it happens
Trigger: Passing filename_prefix like '../foo/img', '/etc/passwd/img', or a subfolder that normalizes above output_dir; also triggered when output_dir is a relative path and the prefix resolves to a sibling directory.
Common situations: Automating Fooocus via its API with a caller-supplied filename_prefix; using wildcard/path templates that include '..' on Windows (where path joining differs); symlinked output folders that break the commonpath comparison.
Related errors
AI-assisted analysis of lllyasviel/Fooocus@ae05379cc9 (2026-08-15).
Data as JSON: /api/errors/c29b5bbf1268ae91.
Report an issue: GitHub.