You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Gallery reads reject an output:-prefixed name with a misleading "path does not exist"; list_gallery can't show a take's duration #356
tool/endpoint:get_gallery_metadata (and every gallery read that resolves a name through _output_file: get_output_audio, get_output_frames, get_output_image, download_output, delete_output); list_gallery repro:
Run any audio template (e.g. templates/minimax/music/... or templates/generate-speech). list_gallery(limit=5) reports name: <folder>/<run>/final/<file>.mp3.
get_gallery_metadata(name="output:<that name>"), spelled the way a workflow argument references an output.
Run a Music 3 template twice so both runs write the same basename (e.g. MiniMaxMusic-balanced.1-0.0.mp3), then list_gallery(). expected: (2) The output: prefix is accepted and stripped, as asset: already is on this endpoint, or it's refused with "drop the 'output:' prefix - gallery tools take the bare name". (3) The listing is enough to choose between the two takes without one metadata call per candidate. actual: (2) Unknown file: output:<name> - path does not exist: the prefix is joined into the path, and the message suggests the file is gone. In the field this nearly led an agent to conclude a score roll had been deleted. (3) Entries now carry run_id/version (Feat/run versions #336) but no duration. The two takes were 75.08 s (keep) and 42.25 s (reject), and size and mtime both pointed the wrong way: the later run was the short one, and the files were 808 KB at 42 s vs 1389 KB at 75 s, a bitrate difference, not a length one. code: dw/server/app.py:2503-2533 _output_file(name, root) does validate_path(os.path.join(root, name), ...) with no reference-prefix handling. The InvalidInputError branch produces "path does not exist". app.py:2913-2921 gallery_metadata special-cases only is_asset_reference(name). app.py:2719-2779 _gallery_entries builds entries with name/folder/subfolder/run_id/version/url/kind/size/mtime/label and no media fields. proposed fix:
In _output_file (so every gallery read benefits), strip one leading output: before joining. Or, if the maintainers prefer a strict surface, raise a 404 whose detail says "names here are bare gallery names - drop the 'output:' prefix". Keep the traversal/containment checks on the stripped name.
Add an opt-in media=true to list_gallery (/api/gallery?media=true) that adds duration_seconds for audio/video entries, using the probe get_gallery_metadata already uses (dw/media_info.probe_media), bounded by limit. Default listing unchanged.
Tests: a prefixed name resolves (or gets the named refusal) on metadata and delete; a traversal attempt via output:../.. is still refused; media=true returns duration for a wav and a mp4. source: dw-findings-ledger DW-27 (T#6, A#15, A#16), triaged 2026-09-22 against develop f11ac2a
Filed from Don's dw findings ledger (dw-findings-ledger.html, DW-27). First-pass triage for applicability and value against open/closed issues and develop @ f11ac2a by claude-opus-5-5 via anthropic (interactive session with Don; code-checking subagents inherited that model).
triage: work — strip a leading output: in _output_file (dw/server/app.py) and add duration to gallery entries. (claude-opus-5-5 via anthropic, triage session)
Changes (commit abc9b61 on develop, branch fix/gallery-output-prefix-356):
_strip_output_prefix(name) (dw/server/app.py) strips one leading output: before a gallery name is used for path resolution, job lookup, or run-path parsing — the way asset: was already handled on these same endpoints. Applied at the top of gallery_metadata, gallery_audio, gallery_frames, delete_output, archive_outputs, keep_output, and the static /outputs/{name} route, plus inside _output_file itself (so gallery_thumbnail/download_output get it for free). Containment is still validate_path's, run on the stripped remainder — traversal via output:../... is still refused.
GET /api/gallery gains an opt-in media=true that adds duration_seconds to audio/video entries via the same probe_mediaget_gallery_metadata already uses, bounded to the page actually returned (post offset/limit) rather than the whole listing. Default listing (no media param) is byte-for-byte unchanged.
Tests added (tests/test_server.py): test_gallery_metadata_accepts_an_output_reference, test_gallery_output_reference_traversal_is_still_refused, test_gallery_delete_accepts_an_output_reference, test_gallery_lists_media_duration_when_asked. Full tests/test_server.py + related server test files (466 tests) pass.
Deploy: ssh lem '~/diffusers-workflow/scripts/deploy.sh develop', systemd unit dw-serve restarted, healthy after 5s at abc9b61 (2026-09-22 00:35 UTC).
Worked as claude-sonnet-5 via anthropic.
Regression-suite proposal for regression-suite-smoke.md (basic, general-purpose gallery-read path):
Run any workflow that writes an audio or video output; call list_gallery() and note a file's name.
Call get_gallery_metadata(name="output:<that name>") — expect it to resolve (media info returned), not 404.
Call list_gallery(media=true) on the same folder — expect the matching entry to carry duration_seconds approximately matching what get_gallery_metadata reports; expect a plain list_gallery() call (no media arg) to carry no duration_seconds field at all.
Verify against develop @ e5bfb9e: part 1 passes, part 2 isn't reachable over MCP. Sending back. (tester, claude-opus-5-5 via anthropic)
Part 1 (output: prefix): confirmed
get_gallery_metadata(name="output:templates/ltx2/text-to-video/20260922-012240-d368e5a2/LTX2-text_to_video.0-0.0.mp4") resolves. It returns the bare name, job 4d2d3ef2e368, version 7, and a media block (duration 5.041667 s, 121 frames, 48 kHz stereo).
Neighbor: get_output_audio with the same output:-prefixed name, start=0, duration=0.5 returned a 0.5 s WAV excerpt.
Traversal: get_gallery_metadata(name="output:../../etc/passwd") is still refused with Unknown file: ../../etc/passwd - path contains a disallowed pattern (the prefix is stripped, then containment applies).
Part 2 (duration in the listing): not fixed at the MCP surface
The MCP list_gallery tool schema has no media parameter. Its params are folder, limit, only_orphans, subfolder, version, workspace. I called list_gallery(folder="templates/minimax/music", limit=3, media=true). The extra argument was silently ignored, and the one audio entry (templates/minimax/music/20260913-050819-61e4c9a5/MiniMaxMusic-generate_music.0-0.0.mp3) came back with no duration_seconds. The hand-off describes media=true on GET /api/gallery only. The issue's endpoint is list_gallery, and an MCP consumer can't reach the HTTP param.
Still needed: expose media: bool = False on the list_gallery MCP tool (passed through to /api/gallery?media=true), and document it in the tool description. Also consider the silent drop: an unknown kwarg to an MCP tool gave no error. That may be FastMCP's default, so I'm only flagging it here, not filing it separately.
triage: work — tester bounced abc9b61: part 1 passes; part 2 (duration on list_gallery entries) isn't reachable over MCP — surface it through the dw_mcp list_gallery tool. (claude-opus-5-5 via anthropic, triage session)
Part 2 fixed and deployed: list_gallery now takes media: bool = False over MCP, forwarded to GET /api/gallery?media=true (which already answered it since the last round).
Changes (commit 1f6a97d on develop, merged from fix-356-list-gallery-media):
dw_mcp/catalog.pylist_gallery() gains a media kwarg, sent as params["media"] = "true" only when set.
dw_mcp/server.pylist_gallery tool gains media: bool = False, passed through, with a docstring sentence naming what it adds. Trimmed elsewhere in the same docstring to stay under the 2048-char client description limit (list_gallery was at 2109 after the addition) and the tool-surface token budget in tests/test_mcp_server.py.
Part 1 (output: prefix handling) was already deployed and verified in the previous round; unchanged here.
Tests added (tests/test_mcp_catalog.py): test_list_gallery_sends_media_only_when_true, mirroring the existing only_orphans/folder+version param tests - asserts media is absent from the outgoing request params by default and sent as "true" only when media=True is passed. tests/test_mcp_catalog.py, tests/test_mcp_server.py, tests/test_mcp_media.py, tests/test_mcp_exports.py, tests/test_mcp_workspaces.py (260 tests) pass, including the tool-surface budget and 2048-char description tests. ruff check clean on the changed files.
Deploy: ssh lem '~/diffusers-workflow/scripts/deploy.sh develop', systemd unit dw-serve restarted, healthy after 5s at 1f6a97d.
To verify: list_gallery(folder="templates/minimax/music", limit=3, media=true) should now return duration_seconds on the audio entry (matching what get_gallery_metadata reports for the same file), and a plain list_gallery() call should still carry no duration_seconds field.
Verified against develop @ 4aaeef7 (includes 1f6a97d). (tester, claude-opus-5-5 via anthropic)
Part 2 (duration in the listing): confirmed over MCP
The list_gallery tool schema now has media: bool = False, and its description says what the flag adds.
list_gallery(folder="templates/minimax/music", limit=3, media=true): the mp3 entry templates/minimax/music/20260913-050819-61e4c9a5/MiniMaxMusic-generate_music.0-0.0.mp3 carries duration_seconds: 30.023401.
The same call without media returns the same entry with no duration_seconds key.
get_gallery_metadata(name="output:templates/minimax/music/.../MiniMaxMusic-generate_music.0-0.0.mp3") resolves through the output: prefix and reports media.duration_seconds: 30.023401, which matches the listing exactly.
Adjacent cases
Video: list_gallery(folder="templates/ltx2/text-to-video", limit=2, media=true) returns duration_seconds 5.041667 (v7, the same figure get_gallery_metadata gave for that file in the last round) and 14.375 (v6).
Non-media: list_gallery(limit=6, media=true) returns six image entries, and none of them has a duration_seconds field.
Part 1 (output: prefix, traversal still refused) was verified in the previous round. The re-check above confirms that the prefix still resolves.
Traversal re-checked this session: get_gallery_metadata(name="output:../../etc/passwd") is refused with 'Unknown file: ../../etc/passwd - path contains a disallowed pattern'. Added smoke case S-F119 (harnest regression-suite-smoke.md) covering the output: prefix and list_gallery(media=true). (tester, claude-opus-5-5 via anthropic)
Activity
dkackman commentedon Sep 22, 2026
triage: work — strip a leading output: in _output_file (dw/server/app.py) and add duration to gallery entries. (claude-opus-5-5 via anthropic, triage session)
fix(server): #356 - accept output: prefix on gallery reads, add media…
dkackman commentedon Sep 23, 2026
Fixed and deployed.
Changes (commit
abc9b61ondevelop, branchfix/gallery-output-prefix-356):_strip_output_prefix(name)(dw/server/app.py) strips one leadingoutput:before a gallery name is used for path resolution, job lookup, or run-path parsing — the wayasset:was already handled on these same endpoints. Applied at the top ofgallery_metadata,gallery_audio,gallery_frames,delete_output,archive_outputs,keep_output, and the static/outputs/{name}route, plus inside_output_fileitself (sogallery_thumbnail/download_outputget it for free). Containment is stillvalidate_path's, run on the stripped remainder — traversal viaoutput:../...is still refused.GET /api/gallerygains an opt-inmedia=truethat addsduration_secondsto audio/video entries via the sameprobe_mediaget_gallery_metadataalready uses, bounded to the page actually returned (postoffset/limit) rather than the whole listing. Default listing (nomediaparam) is byte-for-byte unchanged.Tests added (tests/test_server.py):
test_gallery_metadata_accepts_an_output_reference,test_gallery_output_reference_traversal_is_still_refused,test_gallery_delete_accepts_an_output_reference,test_gallery_lists_media_duration_when_asked. Fulltests/test_server.py+ related server test files (466 tests) pass.Deploy:
ssh lem '~/diffusers-workflow/scripts/deploy.sh develop', systemd unitdw-serverestarted, healthy after 5s atabc9b61(2026-09-22 00:35 UTC).Worked as
claude-sonnet-5viaanthropic.Regression-suite proposal for
regression-suite-smoke.md(basic, general-purpose gallery-read path):list_gallery()and note a file'sname.get_gallery_metadata(name="output:<that name>")— expect it to resolve (media info returned), not 404.list_gallery(media=true)on the same folder — expect the matching entry to carryduration_secondsapproximately matching whatget_gallery_metadatareports; expect a plainlist_gallery()call (nomediaarg) to carry noduration_secondsfield at all.dkackman commentedon Sep 23, 2026
Verify against develop @ e5bfb9e: part 1 passes, part 2 isn't reachable over MCP. Sending back. (tester, claude-opus-5-5 via anthropic)
Part 1 (
output:prefix): confirmedget_gallery_metadata(name="output:templates/ltx2/text-to-video/20260922-012240-d368e5a2/LTX2-text_to_video.0-0.0.mp4")resolves. It returns the barename, job4d2d3ef2e368, version 7, and amediablock (duration 5.041667 s, 121 frames, 48 kHz stereo).get_output_audiowith the sameoutput:-prefixed name,start=0, duration=0.5returned a 0.5 s WAV excerpt.get_gallery_metadata(name="output:../../etc/passwd")is still refused withUnknown file: ../../etc/passwd - path contains a disallowed pattern(the prefix is stripped, then containment applies).Part 2 (duration in the listing): not fixed at the MCP surface
The MCP
list_gallerytool schema has nomediaparameter. Its params arefolder, limit, only_orphans, subfolder, version, workspace. I calledlist_gallery(folder="templates/minimax/music", limit=3, media=true). The extra argument was silently ignored, and the one audio entry (templates/minimax/music/20260913-050819-61e4c9a5/MiniMaxMusic-generate_music.0-0.0.mp3) came back with noduration_seconds. The hand-off describesmedia=trueonGET /api/galleryonly. The issue's endpoint islist_gallery, and an MCP consumer can't reach the HTTP param.Still needed: expose
media: bool = Falseon thelist_galleryMCP tool (passed through to/api/gallery?media=true), and document it in the tool description. Also consider the silent drop: an unknown kwarg to an MCP tool gave no error. That may be FastMCP's default, so I'm only flagging it here, not filing it separately.dkackman commentedon Sep 23, 2026
triage: work — tester bounced abc9b61: part 1 passes; part 2 (duration on list_gallery entries) isn't reachable over MCP — surface it through the dw_mcp list_gallery tool. (claude-opus-5-5 via anthropic, triage session)
fix(mcp): #356 - expose list_gallery(media=true) over MCP
dkackman commentedon Sep 23, 2026
Part 2 fixed and deployed:
list_gallerynow takesmedia: bool = Falseover MCP, forwarded toGET /api/gallery?media=true(which already answered it since the last round).Changes (commit
1f6a97dondevelop, merged fromfix-356-list-gallery-media):dw_mcp/catalog.pylist_gallery()gains amediakwarg, sent asparams["media"] = "true"only when set.dw_mcp/server.pylist_gallerytool gainsmedia: bool = False, passed through, with a docstring sentence naming what it adds. Trimmed elsewhere in the same docstring to stay under the 2048-char client description limit (list_gallerywas at 2109 after the addition) and the tool-surface token budget intests/test_mcp_server.py.output:prefix handling) was already deployed and verified in the previous round; unchanged here.Tests added (
tests/test_mcp_catalog.py):test_list_gallery_sends_media_only_when_true, mirroring the existingonly_orphans/folder+versionparam tests - assertsmediais absent from the outgoing request params by default and sent as"true"only whenmedia=Trueis passed.tests/test_mcp_catalog.py,tests/test_mcp_server.py,tests/test_mcp_media.py,tests/test_mcp_exports.py,tests/test_mcp_workspaces.py(260 tests) pass, including the tool-surface budget and 2048-char description tests.ruff checkclean on the changed files.Deploy:
ssh lem '~/diffusers-workflow/scripts/deploy.sh develop', systemd unitdw-serverestarted, healthy after 5s at1f6a97d.To verify:
list_gallery(folder="templates/minimax/music", limit=3, media=true)should now returnduration_secondson the audio entry (matching whatget_gallery_metadatareports for the same file), and a plainlist_gallery()call should still carry noduration_secondsfield.Worked as
claude-sonnet-5viaanthropic.dkackman commentedon Sep 23, 2026
Verified against develop @ 4aaeef7 (includes 1f6a97d). (tester, claude-opus-5-5 via anthropic)
Part 2 (duration in the listing): confirmed over MCP
list_gallerytool schema now hasmedia: bool = False, and its description says what the flag adds.list_gallery(folder="templates/minimax/music", limit=3, media=true): the mp3 entrytemplates/minimax/music/20260913-050819-61e4c9a5/MiniMaxMusic-generate_music.0-0.0.mp3carriesduration_seconds: 30.023401.mediareturns the same entry with noduration_secondskey.get_gallery_metadata(name="output:templates/minimax/music/.../MiniMaxMusic-generate_music.0-0.0.mp3")resolves through theoutput:prefix and reportsmedia.duration_seconds: 30.023401, which matches the listing exactly.Adjacent cases
list_gallery(folder="templates/ltx2/text-to-video", limit=2, media=true)returnsduration_seconds5.041667 (v7, the same figureget_gallery_metadatagave for that file in the last round) and 14.375 (v6).list_gallery(limit=6, media=true)returns six image entries, and none of them has aduration_secondsfield.Part 1 (
output:prefix, traversal still refused) was verified in the previous round. The re-check above confirms that the prefix still resolves.dkackman commentedon Sep 23, 2026
Traversal re-checked this session: get_gallery_metadata(name="output:../../etc/passwd") is refused with 'Unknown file: ../../etc/passwd - path contains a disallowed pattern'. Added smoke case S-F119 (harnest regression-suite-smoke.md) covering the output: prefix and list_gallery(media=true). (tester, claude-opus-5-5 via anthropic)