Summary
yutu video update consistently fails with Error: failed to get video regardless of the video ID, arguments, or account. The same authenticated session can successfully call yutu video list for the same video ID, confirming the video exists and is readable — but video update cannot retrieve it to perform the PATCH.
This blocks any programmatic metadata updates (flipping privacy from unlisted → public, editing title/description after upload, etc.) and forces users to bypass yutu with raw YouTube API calls.
Environment
- yutu version:
0.10.7 darwin/arm64 (latest stable at time of writing)
- Build:
OpenWaygate-2026-04-07T13:18:53Z
- OS: macOS 15.x (Darwin 25.2.0) on Apple Silicon (arm64)
- Install method: Downloaded binary from GitHub releases
- Authentication: Standard OAuth flow via
client_secret.json + youtube.token.json (Desktop/Web OAuth client, refresh token valid)
Reproduction steps
# Working: video list returns the video resource fine
$ yutu video list --ids ae3hSaEI70o --parts id,status --output json
[
{
"etag": "8LgzvO64p2Bj8T61QjKA339aJ6c",
"id": "ae3hSaEI70o",
"kind": "youtube#video",
"status": {
"embeddable": true,
"license": "youtube",
"privacyStatus": "unlisted",
"publicStatsViewable": true,
"uploadStatus": "processed"
}
}
]
# Broken: video update fails on the exact same ID, same session
$ yutu video update --id ae3hSaEI70o --privacy public --output json
Error: failed to get video
# Also fails with additional fields populated
$ yutu video update --id ae3hSaEI70o --title 'X' --description 'Y' --privacy public
Error: failed to get video
# DEBUG log level doesn't surface the underlying HTTP error
$ YUTU_LOG_LEVEL=DEBUG yutu video update --id ae3hSaEI70o --privacy public
time=2026-04-10T19:12:11.245-04:00 level=DEBUG msg=\"Root directory set\" dir=/Users/urepa/DevWork/Apify
Error: failed to get video
Expected behavior
video update should succeed when video list succeeds for the same video ID on the same authenticated session, and it should apply the requested metadata changes (e.g. privacyStatus: public).
Actual behavior
video update always fails with the string failed to get video, with no additional error detail even at DEBUG log level. The underlying YouTube API error (HTTP status, response body) is not surfaced.
Workaround
Bypass yutu for metadata updates and call PUT https://www.googleapis.com/youtube/v3/videos?part=status directly using the same OAuth token. A 100-line Python script using stdlib urllib handles the full flow (token refresh → GET current resource → PUT updated resource) without yutu. This is what I ended up doing to ship a batch of 5 shorts from unlisted to public.
Suggested fixes / improvements
- Surface the underlying error. Wrapping the API error as
fmt.Errorf(\"failed to get video: %w\", err) would immediately expose whether this is a permissions issue, quota exhaustion, parts mismatch, or something else.
- Investigate the internal
videos.list call that video update makes. It's likely requesting a different set of parts than yutu video list — possibly requesting parts the authenticated user doesn't have access to (fileDetails, processingDetails, etc.) which can trigger 403s on some videos even when the user owns them.
- Consider separating the fetch and update logic. Let users pass a pre-fetched status JSON or use
--part status to restrict the internal GET to only the parts needed for the patch.
Related: missing fields in video insert / video update
While I was debugging this, I also noticed that video insert and video update don't expose several important status fields that are settable via the YouTube Data API v3:
selfDeclaredMadeForKids (audience declaration — there's --forKids but it maps to a different field)
containsSyntheticMedia (the new Altered Content / AI-generated disclosure — mandatory for AI content per YouTube policy)
recordingDate
topicDetails
I'll file these as a separate feature request so this bug stays focused. Happy to contribute a PR for any of the above if helpful.
Impact
This bug affects anyone trying to use yutu in a batch upload pipeline where videos are uploaded as unlisted first, reviewed, and then flipped to public programmatically. It's the natural use case for a creator tool, and the one-way-only upload (with no follow-up edits) is a major limitation in its current state.
Reported by a real user shipping a 5-video batch from the Zero Tax Tags channel. Happy to help debug further or test a fix — just ping me.
Summary
yutu video updateconsistently fails withError: failed to get videoregardless of the video ID, arguments, or account. The same authenticated session can successfully callyutu video listfor the same video ID, confirming the video exists and is readable — butvideo updatecannot retrieve it to perform the PATCH.This blocks any programmatic metadata updates (flipping privacy from unlisted → public, editing title/description after upload, etc.) and forces users to bypass yutu with raw YouTube API calls.
Environment
0.10.7 darwin/arm64(latest stable at time of writing)OpenWaygate-2026-04-07T13:18:53Zclient_secret.json+youtube.token.json(Desktop/Web OAuth client, refresh token valid)Reproduction steps
Expected behavior
video updateshould succeed whenvideo listsucceeds for the same video ID on the same authenticated session, and it should apply the requested metadata changes (e.g.privacyStatus: public).Actual behavior
video updatealways fails with the stringfailed to get video, with no additional error detail even at DEBUG log level. The underlying YouTube API error (HTTP status, response body) is not surfaced.Workaround
Bypass yutu for metadata updates and call
PUT https://www.googleapis.com/youtube/v3/videos?part=statusdirectly using the same OAuth token. A 100-line Python script using stdliburllibhandles the full flow (token refresh → GET current resource → PUT updated resource) without yutu. This is what I ended up doing to ship a batch of 5 shorts from unlisted to public.Suggested fixes / improvements
fmt.Errorf(\"failed to get video: %w\", err)would immediately expose whether this is a permissions issue, quota exhaustion, parts mismatch, or something else.videos.listcall thatvideo updatemakes. It's likely requesting a different set ofpartsthanyutu video list— possibly requesting parts the authenticated user doesn't have access to (fileDetails,processingDetails, etc.) which can trigger 403s on some videos even when the user owns them.--part statusto restrict the internal GET to only the parts needed for the patch.Related: missing fields in
video insert/video updateWhile I was debugging this, I also noticed that
video insertandvideo updatedon't expose several importantstatusfields that are settable via the YouTube Data API v3:selfDeclaredMadeForKids(audience declaration — there's--forKidsbut it maps to a different field)containsSyntheticMedia(the new Altered Content / AI-generated disclosure — mandatory for AI content per YouTube policy)recordingDatetopicDetailsI'll file these as a separate feature request so this bug stays focused. Happy to contribute a PR for any of the above if helpful.
Impact
This bug affects anyone trying to use yutu in a batch upload pipeline where videos are uploaded as unlisted first, reviewed, and then flipped to public programmatically. It's the natural use case for a creator tool, and the one-way-only upload (with no follow-up edits) is a major limitation in its current state.
Reported by a real user shipping a 5-video batch from the Zero Tax Tags channel. Happy to help debug further or test a fix — just ping me.