Problem
Loading an image from outside the workspace into a LoadImage node produces a 0-byte file in {inputs}, and the image renders broken. Re-evaluating the node truncates a previously-good file back to 0 bytes.
Expected: the external file is copied into {inputs} intact, and an existing file with the same name is never clobbered — the copy_external_file situation declares CREATE_NEW, so a second load should allocate name_001.png.
Origin
Reported by Jason Schleifer on main. Reproducible: pick any image from a directory outside the workspace in LoadImage. The source file is valid (confirmed intact PNG); the emptiness is introduced on our side.
Impact
Loading external images — the common first step in most workflows — silently produces empty files. Worse, a file the user copied into {inputs} by hand gets destroyed the next time the node evaluates, so the manual workaround doesn't hold.
Repro / evidence
- Put an image outside the workspace.
- In
LoadImage, browse to it and select it.
- The preview is broken and
{inputs}/images/<name>.png is 0 bytes.
- Copy the image into
{inputs} manually, select it, then evaluate the node — it is truncated to 0 bytes again.
Warning logged during the copy:
WARNING Attempted to identify the format of bytes destined for '/Users/<user>/.../GriptapeNodes/inputs/images/<name>.png'.
Could not recognize the bytes as a known file format, so the file will be written with its requested '.png'
extension unchanged.
Two things line up with the symptoms:
LocalStorageDriver.create_signed_upload_url writes an empty placeholder (content=b"", local_storage_driver.py) to claim the destination before handing out the PUT url. That empty write is what the format sniffer is complaining about — the bytes it is asked to identify are the placeholder's, not the image's. So the warning fires on the normal path and is misleading.
on_handle_create_static_file_upload_url_request (static_files_manager.py) calls create_signed_upload_url(resolved.path, file_metadata=resolved.file_metadata) and does not pass resolved.policy, so the call takes the parameter default ExistingFilePolicy.OVERWRITE instead of the CREATE_NEW the situation declares. save_static_file threads the resolved policy through; this path does not.
That accounts for the broken first render (the display url is served while only the placeholder exists), the re-zeroing on evaluate (a second upload-url request overwrites the good file with the placeholder rather than allocating an indexed name), and why a manual copy alone works (no upload-url request, so no placeholder).
No unit test covers the manager's upload-url path passing the resolved policy through — tests/unit/drivers/storage/test_base_storage_driver.py covers the driver-level pass-through only.
Problem
Loading an image from outside the workspace into a
LoadImagenode produces a 0-byte file in{inputs}, and the image renders broken. Re-evaluating the node truncates a previously-good file back to 0 bytes.Expected: the external file is copied into
{inputs}intact, and an existing file with the same name is never clobbered — thecopy_external_filesituation declaresCREATE_NEW, so a second load should allocatename_001.png.Origin
Reported by Jason Schleifer on
main. Reproducible: pick any image from a directory outside the workspace inLoadImage. The source file is valid (confirmed intact PNG); the emptiness is introduced on our side.Impact
Loading external images — the common first step in most workflows — silently produces empty files. Worse, a file the user copied into
{inputs}by hand gets destroyed the next time the node evaluates, so the manual workaround doesn't hold.Repro / evidence
LoadImage, browse to it and select it.{inputs}/images/<name>.pngis 0 bytes.{inputs}manually, select it, then evaluate the node — it is truncated to 0 bytes again.Warning logged during the copy:
Two things line up with the symptoms:
LocalStorageDriver.create_signed_upload_urlwrites an empty placeholder (content=b"",local_storage_driver.py) to claim the destination before handing out the PUT url. That empty write is what the format sniffer is complaining about — the bytes it is asked to identify are the placeholder's, not the image's. So the warning fires on the normal path and is misleading.on_handle_create_static_file_upload_url_request(static_files_manager.py) callscreate_signed_upload_url(resolved.path, file_metadata=resolved.file_metadata)and does not passresolved.policy, so the call takes the parameter defaultExistingFilePolicy.OVERWRITEinstead of theCREATE_NEWthe situation declares.save_static_filethreads the resolved policy through; this path does not.That accounts for the broken first render (the display url is served while only the placeholder exists), the re-zeroing on evaluate (a second upload-url request overwrites the good file with the placeholder rather than allocating an indexed name), and why a manual copy alone works (no upload-url request, so no placeholder).
No unit test covers the manager's upload-url path passing the resolved policy through —
tests/unit/drivers/storage/test_base_storage_driver.pycovers the driver-level pass-through only.