LocalAI version:
localai/localai:latest-gpu-nvidia-cuda-13 which corresponds to LocalAI v4.6.0 (Commit hash: 38350d3). The issue appears valid and present in the master branch as well.
Environment, CPU architecture, OS, and Version:
OS: Ubuntu 26.04 LTS (Host machine running Docker)
Architecture: x86_64 (Intel CPU)
Hardware: NVIDIA RTX 3090
Diffusers backend: cuda13-diffusers
Describe the bug
When utilizing the Python diffusers backend wrapper, image generation requests complete their GPU inference cycles but fail during the final file-saving phase. The core Go server allocates an absolute temporary path ending in .tmp (e.g., /staging/localai-output-xxx.tmp) and passes it down via gRPC as request.dst.
Because the Python script tries to save the output matrix using image.save(request.dst) without passing an explicit format parameter, the underlying Pillow library attempts to guess the encoder by slicing the file extension. Seeing .tmp, it throws an unhandled unknown file extension: .tmp error, instantly crashing the worker thread.
To Reproduce
Create a model configuration file named animagine-xl.yaml with the following contents:
YAML
backend: diffusers
cfg_scale: 7
diffusers:
cuda: true
enable_parameters: negative_prompt,num_inference_steps
pipeline_type: StableDiffusionXLPipeline
scheduler_type: euler_a
f16: true
name: animagine-xl
parameters:
model: animagine-xl-4.0-opt.safetensors
step: 50
Start LocalAI via Docker using the latest-gpu-nvidia-cuda-13 image.
Open the LocalAI built-in Web UI (IHM) in your browser.
Navigate to the image generation interface, select the animagine-xl model, type a prompt (e.g., "cat"), and trigger the generation.
Expected behavior
The image should generate and display successfully in the Web UI. The Python backend wrapper should explicitly define the saving format to override Pillow's extension-guessing mechanics if a temporary file path string ending in .tmp is provided by the core engine.
Logs
During the runtime workflow, the Go core engine generates a temporary asset path tracker:
Data Fields
destination /tmp/generated/content/images/b643240731440.png
height 512
negative_prompt
positive_prompt: cat
seed -1
source_image
step 50
width 512
The string is passed directly into the Python layer (backend/python/diffusers/backend.py), which attempts to save:
The request object:
height: 512
width: 512
step: 50
seed: -1
positive_prompt: "cat"
dst: "/staging/localai-output-1310138610.tmp"
EnableParameters: "negative_prompt,num_inference_steps
Python
image.save(request.dst)
The execution loop aborts right at the finish line:
Plaintext
rpc error: code = Unknown desc = Exception calling application: unknown file extension: .tmp
LocalAI version:
localai/localai:latest-gpu-nvidia-cuda-13 which corresponds to LocalAI v4.6.0 (Commit hash: 38350d3). The issue appears valid and present in the master branch as well.
Environment, CPU architecture, OS, and Version:
OS: Ubuntu 26.04 LTS (Host machine running Docker)
Architecture: x86_64 (Intel CPU)
Hardware: NVIDIA RTX 3090
Diffusers backend: cuda13-diffusers
Describe the bug
When utilizing the Python diffusers backend wrapper, image generation requests complete their GPU inference cycles but fail during the final file-saving phase. The core Go server allocates an absolute temporary path ending in .tmp (e.g., /staging/localai-output-xxx.tmp) and passes it down via gRPC as request.dst.
Because the Python script tries to save the output matrix using image.save(request.dst) without passing an explicit format parameter, the underlying Pillow library attempts to guess the encoder by slicing the file extension. Seeing .tmp, it throws an unhandled unknown file extension: .tmp error, instantly crashing the worker thread.
To Reproduce
Create a model configuration file named animagine-xl.yaml with the following contents:
YAML
Start LocalAI via Docker using the latest-gpu-nvidia-cuda-13 image.
Open the LocalAI built-in Web UI (IHM) in your browser.
Navigate to the image generation interface, select the animagine-xl model, type a prompt (e.g., "cat"), and trigger the generation.
Expected behavior
The image should generate and display successfully in the Web UI. The Python backend wrapper should explicitly define the saving format to override Pillow's extension-guessing mechanics if a temporary file path string ending in .tmp is provided by the core engine.
Logs
During the runtime workflow, the Go core engine generates a temporary asset path tracker:
Data Fields
destination /tmp/generated/content/images/b643240731440.png
height 512
negative_prompt
positive_prompt: cat
seed -1
source_image
step 50
width 512
The string is passed directly into the Python layer (backend/python/diffusers/backend.py), which attempts to save:
The request object:
height: 512
width: 512
step: 50
seed: -1
positive_prompt: "cat"
dst: "/staging/localai-output-1310138610.tmp"
EnableParameters: "negative_prompt,num_inference_steps
Python
image.save(request.dst)
The execution loop aborts right at the finish line:
Plaintext
rpc error: code = Unknown desc = Exception calling application: unknown file extension: .tmp