YouTube API uploadStatus rejected: the one-word verdict that kills your upload
The upload finished. The API returned a video resource with a real video ID. Nothing in your logs looks wrong. Then status.uploadStatus comes back as rejected, and the only explanation you are given is a single word — one of ten — with no detail, no field pointer, and no appeal route anywhere in the API.
The core problem is not the rejection. It is the resolution. A rejected video is a business event — a copyright dispute, a trademark complaint, a duplicate, a suspended account — delivered to your software as one lowercase token. Your code has to decide what to tell the customer, whether to retry, whether to escalate, and whether the account is even still usable, from a word.
The three fields that decide whether an upload lived or died
YouTube’s Videos resource reference splits the verdict across three properties inside the status object, and they are mutually exclusive in a way that trips people up.
status.uploadStatus
The headline verdict. Documented values: deleted, failed, processed, rejected, uploaded. Everything else hangs off this one field.
status.failureReason
Only present when the upload failed — a technical fault with the file or the transfer. Six documented values, all fixable by you.
status.rejectionReason
Only present when the upload was rejected — a policy, rights or account decision. Ten documented values, almost none fixable by you.
processingDetails
A separate lifecycle entirely. A video can be accepted and still never become watchable, and that failure is reported nowhere in the status object.
The distinction between failed and rejected is the one that matters commercially. Failed is an engineering problem. Rejected is a legal, policy or account problem — and a retry loop that treats them the same will hammer YouTube with re-uploads of content that was never going to be accepted.
The ten rejection verdicts, and what each one actually is
Every value below is published verbatim in the Videos resource reference as a valid value of status.rejectionReason. What YouTube does not publish is any sub-reason, any pointer to the offending claim, or any structured way to act on it. The second column is the business problem sitting behind the word.
| rejectionReason | What it really means for the product |
|---|---|
claim | A rights holder has asserted a claim against the content. This is a rights-clearance conversation, not a bug. |
copyright | Copyright enforcement. If your platform accepts user-supplied media, this is the value that eventually forces you to build an intake and takedown story. |
duplicate | Frequently self-inflicted — a retry, a resumable-upload restart, or a queue that redelivered the same job. Your own reliability logic can manufacture this one. |
inappropriate | Community-guidelines enforcement against the content itself. |
legal | A legal removal. Nothing in the API tells you the jurisdiction, the complainant, or the scope. |
length | The video exceeds a limit the channel is allowed. Commonly an unverified-account ceiling rather than a defect in your file. |
termsOfUse | A Terms of Service breach. Read this as a signal about the account, not just the video. |
trademark | A trademark complaint — often triggered by title, description or branding metadata your product generated, not by the footage. |
uploaderAccountClosed | Not about the video at all. The connected account is gone. Every queued job for that account is already dead. |
uploaderAccountSuspended | Not about the video at all. The account is suspended. Continuing to push uploads at it is pure waste, and your dashboard will keep reporting per-video failures for an account-level condition. |
The last two are the expensive ones. uploaderAccountClosed and uploaderAccountSuspended are account-state facts wearing the costume of a per-video rejection. A multi-tenant uploader that does not special-case them will retry, alert, and bill against an account that cannot receive a video at all — and the customer-facing message it generates will be wrong in a way that damages trust.
The six failure reasons — and why they are the good news
When uploadStatus is failed, status.failureReason carries one of six documented values: codec, conversion, emptyFile, invalidFile, tooSmall, uploadAborted. These are the ones your pipeline can genuinely own. They point at transcoding, at a truncated transfer, at a file that never had bytes in it, or at a client that gave up mid-stream.
The trap is that several of them are produced by your infrastructure rather than by the user’s file — a storage read that returned early, a proxy that terminated a long resumable upload, a re-encode step that emitted a container YouTube will not take. Teams routinely report these to customers as “your video was rejected”, which is both inaccurate and unrecoverable from the customer’s side.
The third failure lifecycle nobody instruments
Even a clean uploaded or processed status is not a promise that the video works. processingDetails.processingStatus runs its own state machine with the documented values failed, processing, succeeded and terminated. When it is failed, processingDetails.processingFailureReason gives you other, streamingFailed, transcodeFailed or uploadFailed.
And terminated deserves reading twice: the documentation defines it as “Processing information is no longer available.” That is not a success and not a failure — it is the platform telling you the answer has expired. If your job tracker polls for a terminal state and only recognises success and failure, those videos sit in your queue forever.
Separately, suggestions.processingErrors[] can tell you in advance that processing will almost certainly end in failure — with values like archiveFile, audioFile, docFile, imageFile, notAVideoFile and projectFile. In other words: users regularly upload a ZIP, an MP3, a Word document or a Movie Maker project file into a video pipeline, and the API will happily accept the bytes first and tell you afterwards.
What YouTube does not give you
Do not build a support process that assumes these exist
- Any detail behind the verdict. No claimant, no matched reference, no policy clause, no timestamp range, no field pointer. One word is the entire payload.
- Any appeal endpoint. There is no API method to contest a
rejectionReason. Whatever remedy exists lives in the YouTube Studio interface, under the channel owner’s login — not yours. - Any distinction inside a value.
copyrightcovers a full match and a marginal one identically.legalcovers every jurisdiction identically. - Any documented latency. Nothing states how long after upload a rejection can appear, so “it uploaded fine” is never a final answer at the moment of the API call.
- Any account-health signal. The only way you learn an account is closed or suspended is by trying to upload to it and reading a per-video field.
- Any approval or rejection rates. YouTube publishes no statistics here, and neither should anyone quoting them to you.
Where upload products actually break on this
- Treating
failedandrejectedas one error class, so a policy rejection enters a technical retry loop - Retrying a
duplicaterejection, which produces more duplicates and burns the daily upload allowance - Never reading the
statuspart back at all — the upload call returned 200, so the job is marked complete and the failure is discovered by the customer - Reporting
uploaderAccountSuspendedto the end user as a video problem, sending them to re-edit footage that was never the issue - Polling only
uploadStatusand neverprocessingDetails, soterminatedandtranscodeFailedvideos accumulate silently - Ignoring
suggestions.processingErrors[], and spending upload capacity on files that are provably not videos - Surfacing the raw token in the product UI, so customers are shown the word
termsOfUsewith no explanation and open a support ticket you cannot answer - Building the rejection taxonomy into database enums and analytics without a fallback path, so a value YouTube adds later — as it has before — breaks ingestion
- Assuming a rejected upload can be re-pushed under a different title or account, which converts a content problem into an account-standing problem
Why this is harder than it looks from the reference page
The taxonomy has to be mapped to decisions, not messages
Ten rejection values collapse into a much smaller set of actions: stop the account, stop the video, tell the user something specific, or escalate to a human. Getting that mapping wrong is what generates support load, and it cannot be derived from the documentation — it depends on who your users are and what they uploaded.
Account-level and video-level conditions arrive on the same wire
Two of the ten values invalidate every other job for that connection. A queue design that does not have a concept of a poisoned connection will keep working through a backlog that is already void.
The customer-facing wording is a compliance surface
Telling a user their video was removed for
copyrightorlegalreasons is a statement with consequences. It has to be accurate about what YouTube said, and careful about what it does not know — because the API told you almost nothing.The rejection risk should shape the product before launch
Whether you accept arbitrary user media, whether you generate titles and descriptions automatically, whether you allow re-uploads — each of those decisions changes which of the ten values you will see most, and they are far cheaper to change on a whiteboard than in production.
None of it is visible until you are already at volume
A pilot with twenty uploads will show none of this. The failure modes emerge exactly when the pipeline matters, and by then the retry logic, the customer messaging and the database schema are all committed.
The shape of the work
An uploader that reports success on a 200 response and discovers dead videos through customer complaints
Mapping every documented status, failure and rejection value to a decision, an account action and a message the user can act on
A pipeline that knows the difference between a broken file, a rejected video and an account that is gone
This is where an upload integration stops being an API-call problem and becomes a policy and product problem. It sits alongside the project-level rule that can lock every one of your uploads private in the first place — covered in YouTube API uploads locked as private — and the quota and audit process that governs how many uploads you are allowed to attempt at all, covered in our YouTube Data API quota increase and compliance audit guide. If you are also storing or computing anything from what comes back, the derived metrics and data storage rules apply to that too.
Preparing an upload product so it survives audit, handles the full rejection taxonomy, and describes itself accurately to both YouTube and its own users is the preparation work covered by our YouTube API approval and verification support.
Field names, enumerated values and definitions quoted from the official YouTube Data API v3 Videos resource reference as published on 8 July 2026. Google updates these documents without notice — always confirm against the current official reference before making an engineering decision. This is independent approval and compliance support, not affiliation with or endorsement by YouTube or Google, and no specific outcome or timeline can be promised.