Skip to content

fix(data): refuse an image media id instead of blaming the project, the trash and your prompt (#877) - #878

Merged
ffroliva merged 1 commit into
developfrom
bugfix/877-data-download-video-only
Sep 18, 2026
Merged

ffroliva merged 1 commit into
developfrom
bugfix/877-data-download-video-only

Conversation

@ffroliva

@ffroliva ffroliva commented Sep 18, 2026 •

Copy link
Copy Markdown
Owner

The bug

gflow data download recovers video only. The signed URL it needs comes from the as29s record Flow emits when a clip's own route loads, and an image's route does not carry one — so an image media id could never work.

It was accepted anyway: the command opened Chrome, waited 45 s, and produced three guesses for a condition the catalog row states outright.

migrated host: no signed media URL for 4814faa7-… within 45s of opening its clip route.
The media id may belong to another project, or the clip may have been moved to trash in Flow.
-> Check request payload parameters or retry with a simpler prompt text. File a bug …

Measured live 2026-09-18 against an image generated twelve minutes earlier, in that project, not trashed, catalog row intact. Wrong project — no. Trashed — no. Simpler prompt — there is no prompt; it is a download command.

The fix

download_media reads asset.kind before anything else and exits 11:

Configuration error: Media '4814faa7-…' is image, and `gflow data download` recovers
video only. The signed URL it needs comes from the record Flow emits when a clip's own
route loads, and an image's route does not carry one. Tracking the image path in #877.
-> Nothing to retry — this is a capability gap, not a fault. Open the image in Flow and
save it from there, or pass a video media id. `gflow data list images` shows which rows
are images.

No browser, no wait. record_local_file hardcoding media_type="video/mp4" was the other sign this path was always video-only.

The timeout that remains — for a video Flow genuinely does not report — drops the inherited generation-payload remediation and describes what to actually check.

Surfaces corrected. The CLI help, the gflow_download_media MCP description and docs/USAGE.md each said "asset". All three now say video and name the refusal.

The part worth reading

The first version of this fix passed every test and was still wrong.

The detail was right, but ConfigurationError's class-default remediation took over:

Check that the transport name is registered via make_transport(). Run gflow config list-transports …

One misleading hint swapped for another — green the whole way, because the tests asserted the detail and not the hint. A live run caught it.

That is the same defect the fix is about, one level up, and it is now the fourth instance this session: a class-default remediation written for one situation, inherited by a raise site in another (#803, #875, #877, and this). The test now asserts the remediation and carries the story in a comment.

Tests

  • test_refuses_an_image_before_launching_a_browser — asserts the refusal, that no browser is launched, that the old guesses are gone, and that the remediation is not the transport-registry default.
  • test_the_mcp_twin_refuses_an_image_too — its own test, not inherited trust. The twin does not re-raise: _guarded funnels a GFlowError into a problem-details envelope, so what needed pinning is that the reason survives the conversion. An agent handed a masked generic failure would retry an id that can never work.

254 recovery + MCP tests pass.

Verification

Live, on a profile Flow serves from flow.google.com, $0:

  • before: 45 s → exit 7, three false causes
  • after: immediate → exit 11, detail and remediation both true (output quoted above, run against the real catalog and a real media id)

Gates: ruff check · ruff format · repo hygiene (1170 files) · doc links (197 files) · website mirror regenerated and in sync · website PII · pyright src 0 errors.

No Flow surface behaviour changed — the refusal happens before any transport call — so no new e2e is owed. The existing tests/e2e/test_data_download_e2e.py covers the video path it does not touch.

Closes #877

Summary by CodeRabbit

  • New Behavior

    • Video downloads now reject image media IDs immediately with exit code 11, before browser or network activity.
    • Video recovery continues using signed clip URLs, with downloaded content verified before saving.
    • Missing video URLs now provide clearer guidance to verify the clip is available and playable before retrying.
  • Documentation

    • CLI, MCP, and usage documentation now clearly describe video-only download support and image-specific remediation.

…he trash and your prompt (#877)

`gflow data download` recovers video only. The signed URL comes from the
`as29s` record Flow emits when a clip's own route loads, and an image's route
does not carry one — so an image id could never work.

It was accepted anyway. The command opened Chrome, waited 45 s, and produced
three guesses for a condition the catalog row states outright: wrong project,
clip moved to trash, and — inherited from WireFormatError's class default —
"retry with a simpler prompt text", on a command that has no prompt. Measured
live on 2026-09-18 against an image generated twelve minutes earlier, in that
project, not trashed, catalog row intact. None of the three applied.

`download_media` now reads `asset.kind` before anything else and exits 11.
`record_local_file` hardcoding `media_type="video/mp4"` was the other sign this
path was always video-only.

The timeout that remains, for a video Flow genuinely does not report, drops the
generation-payload remediation and says what to actually check.

Surfaces that claimed more than the code delivers, all corrected: the CLI help,
the `gflow_download_media` MCP description, and docs/USAGE.md each said "asset".

A note on the fix's own first version, because it is the same bug one level up:
it passed every test and was still wrong. The detail was right, but
ConfigurationError's class-default remediation took over and told the user to
"check that the transport name is registered via make_transport()". One
misleading hint swapped for another, green the whole way, because the tests read
the detail and not the hint. A live run caught it. The test now asserts the
remediation, and carries that story.

The MCP twin gets its own test rather than trusting the shared service: it does
not re-raise, it funnels through `_guarded` into a problem-details envelope, so
what needed pinning is that the reason survives the conversion — an agent handed
a generic failure would retry an id that can never work.
@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f6b50465-01bd-4930-9cb6-4ab782274ba3

📥 Commits

Reviewing files that changed from the base of the PR and between 4ada6c0 and 9ece55f.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • docs/USAGE.md
  • src/gflow_cli/api/transports/migrated_recover.py
  • src/gflow_cli/cli_data.py
  • src/gflow_cli/mcp/tools.py
  • src/gflow_cli/services/media_recovery.py
  • tests/services/test_media_recovery.py
  • website/docs/USAGE.md

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The download path now rejects image media IDs before browser or network activity. Video recovery continues through signed URLs, with updated clip-specific errors and video-only CLI, MCP, and documentation text.

Changes

Video media recovery

Layer / File(s) Summary
Video-only validation
src/gflow_cli/services/media_recovery.py, tests/services/test_media_recovery.py
download_media rejects non-video media with ConfigurationError before browser launch. Service and MCP tests verify the video-only message, image remediation, and issue #877.
Clip recovery error messaging
src/gflow_cli/api/transports/migrated_recover.py
Missing signed-URL errors now use clip-specific remediation and retain the media ID and timeout details.
Video-only documentation
src/gflow_cli/cli_data.py, src/gflow_cli/mcp/tools.py, docs/USAGE.md, website/docs/USAGE.md, CHANGELOG.md
Documentation and the changelog describe video-only downloads, immediate image rejection with exit 11, and signed-URL recovery through the clip route.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: kittinan

Merge Risk: ⚪ Minimal · up to 9ece5

Image downloads now fail immediately with the documented video-only error, while video recovery behavior remains available. No actionable merge risk is identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 5 files. (3 skipped: 3… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: image media IDs are refused instead of producing misleading project, trash, or prompt-related errors.
Linked Issues check ✅ Passed Issue #877 requires immediate refusal of non-video media IDs, removal of misleading remediation, and video-only wording on user-facing surfaces. download_media resolves the catalog row, rejects non-…
Out of Scope Changes check ✅ Passed The changes stay within Issue #877. The service guard, transport error text, tests, CLI and MCP descriptions, documentation, and changelog all support the requested video-only behavior or its user-fac…
Full details: Docstring Coverage

Explanation

Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 5 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@ffroliva
ffroliva merged commit 20e4687 into develop Sep 18, 2026
19 checks passed
@ffroliva
ffroliva deleted the bugfix/877-data-download-video-only branch September 18, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gflow data download accepts an image media id, waits 45s, then blames the project, the trash, and your prompt

1 participant