Oh. Basically, ZeroGPU quota is consumed on a reservation basis. Unless the author of that ZeroGPU Space explicitly sets another value in code, each call requests the default 60-second reservation. A failed generation, or one whose actual inference finishes much faster, does not retroactively change the size of that reservation. This follows from the core way ZeroGPU works and is one of the structural trade-offs behind making this class of GPU access affordable, so applying a purely mechanical refund to every failed attempt would be much harder than it sounds.
That said, I think your frustration is completely understandable from the user side.
You interact with an image/video generator, so it is natural to think that the quota is paying for a successfully generated image or video. If the page returns an error and gives you nothing, it feels as though no service was delivered.
The more accurate mental model is different:
You are not purchasing a successful output. You are booking a block of runtime on a shared GPU pool.
So, yes: a failed attempt can consume the reserved quota even when no usable result reaches you.
The current ZeroGPU documentation describes ZeroGPU as shared infrastructure that dynamically assigns and releases GPUs. A Space author marks the GPU portion of the application with @spaces.GPU and may specify a duration. If no duration is supplied, the default request is 60 seconds.
Hugging Face’s more detailed ZeroGPU implementation guide and its quota reference make the accounting model clearer:
- the platform compares the requested duration with the visitor’s remaining quota before running the call;
- it does not use the eventual actual runtime for that admission check;
- an unspecified
@spaces.GPUcall requests the default 60 seconds; - that quota is reserved up front;
- shorter declared durations also receive better queue priority;
xlargerequests count at twice the declared duration.
This does not necessarily mean that a physical GPU is kept idle for the entire reserved 60 seconds. The GPU worker can finish and be released earlier. The quota reservation, the actual worker lifetime, and the delivery of the final image/video are three separate layers.
For a practical next step, I would avoid repeatedly retrying the same broken Space. Save the Space URL, the exact error text, and the approximate time of the attempt.
- If it happens only in one Space, report it in that Space’s Community tab.
- If unrelated ZeroGPU Spaces fail in the same way, it may be an account, authentication, quota, scheduler, or platform-level issue rather than one broken generator.
- If the message was specifically “No GPU was available for you”, mention that exact wording. It describes a different failure point from a Python, CUDA, model, or output-encoding error.
How the reservation model works, and why automatic refunds are not simple
Reservation, execution, and output are different things
It helps to separate three stages:
| Layer | What it means | What the user sees |
|---|---|---|
| Requested reservation | The duration declared by the Space author, or 60 seconds by default |
Usually not shown clearly |
| Actual GPU execution | How long the worker really takes before it finishes or fails | A spinner, queue status, progress, or an error |
| Delivered result | Whether an image/video survives post-processing and reaches the browser | A usable output—or nothing |
For example, a Space may request 60 seconds, perform 15 seconds of GPU inference, and then fail while encoding or saving the video. From the visitor’s perspective, the generation failed completely. From the resource scheduler’s perspective, however, a reservation was accepted and GPU work was performed.
That distinction explains why:
- finishing faster does not automatically shrink an existing reservation;
- an application error does not automatically prove that no GPU resource was used;
- not receiving an image does not necessarily mean the failure happened before inference;
- releasing the GPU worker early is not the same thing as retrospectively recalculating the visitor’s quota.
The underlying worker model is described in Hugging Face’s ZeroGPU mechanism reference: the long-lived web application and the short-lived GPU worker are separate processes, and GPU workers may be created or reused when a decorated function is called.
Why use reservations at all?
ZeroGPU is inexpensive because Spaces do not each hold a dedicated GPU continuously, including while nobody is using them. Many applications share a GPU pool, and GPUs are assigned when needed.
That improves utilization, but the scheduler has to make decisions before the final runtime is known:
- whether the user has enough quota for the request;
- whether the request fits the user’s per-call limit;
- where it belongs in the queue;
- how it competes with requests from other Spaces;
- whether the requested GPU size is available.
The declared duration is therefore not just an informational estimate recorded after completion. It is an input to admission control, quota reservation, and queue scheduling.
This is the trade-off: users receive temporary access to powerful shared hardware without each Space paying for a permanently allocated GPU, but the service behaves more like booking shared compute capacity than purchasing a guaranteed finished product.
The low price comes primarily from dynamic sharing and higher utilization, not from failed requests themselves. Duration-based quota accounting is one of the mechanisms that makes that shared pool manageable.
The Space author controls the reservation
There is also an asymmetry that is easy to miss:
- the Space author chooses the
duration; - the visitor’s account pays the quota cost.
If the author does not set it, the visitor receives the default 60-second request even if the normal task takes only a few seconds.
For short fixed workloads, an author can declare a tighter value. For variable workloads, ZeroGPU supports a callable that estimates duration from inputs such as step count, resolution, or frame count.
That is usually better than reserving the same worst-case amount for every request:
- light inputs reserve less quota;
- the request is accepted when the visitor has less quota remaining;
- shorter requests rank better in the queue;
- unnecessarily large reservations are avoided.
The official guide also recommends using xlarge only when necessary, because it doubles the quota request.
Authors can additionally reduce avoidable failures by:
- validating files and inputs before entering the GPU-decorated function;
- keeping expensive CPU preprocessing or output encoding outside the reserved GPU region when practical;
- avoiding many small
@spaces.GPUcalls inside a loop; - using one appropriately sized GPU call for a complete batch or video operation;
- avoiding hidden retries;
- exposing more specific errors than a generic “worker error”;
- using supported acceleration methods such as ZeroGPU ahead-of-time compilation when applicable.
Why not automatically refund anything labelled “failed”?
The following is general systems-design reasoning, not a published statement of Hugging Face’s internal policy.
“Failed generation” can refer to very different events:
- the input was invalid before any GPU request;
- the request was queued but no worker became available;
- CUDA initialization failed;
- model weights failed to load;
- inference ran partly and hit an out-of-memory error;
- inference completed, but image/video encoding failed;
- the result was saved, but transmission to the browser failed;
- the browser disconnected;
- the user pressed Stop, but a normal backend function was already running;
- an outer application failed after successfully calling another model or Space;
- an automatic retry submitted the job several times;
- useful GPU computation completed, but the program deliberately or accidentally raised an exception at the end.
A universal refund system would first need a stable definition of “success”:
- no Python exception?
- HTTP 200?
- an output file exists?
- the browser received the file?
- the file is valid?
- the user considers the result useful?
Those definitions do not produce the same answer.
There is also an abuse boundary. If any final exception automatically restored the reservation, a client or Space could consume GPU computation and deliberately fail only at the last step. That does not prove this was Hugging Face’s stated reason for the policy, but it shows why a completely automatic “error equals full refund” rule is difficult to apply safely and consistently.
None of this means that Hugging Face could never make an individual adjustment after a platform incident. Manual support decisions or internal accounting corrections are a separate question from the normal mechanical reservation flow.
Similar-looking cases, useful checks, and references
Similar symptoms do not always have the same cause
| Symptom | Possible layer | Useful next step |
|---|---|---|
| Python/CUDA/model traceback after the job starts | Space code, dependency, model, memory, or runtime compatibility | Report it to the Space author with the full traceback |
| Error during video/image saving or display | Post-processing, filesystem, serialization, or transport | Note whether inference appeared to finish before the error |
Waiting for a GPU followed by No GPU was available for you |
Scheduler/allocator boundary | Record the timestamp and report the exact sequence |
Immediate quota exceeded |
Requested duration exceeds remaining quota, per-call duration cap, or a separate request-count limit | Do not assume the visible message identifies the exact limiter |
| Works on the normal HF page but fails through API/embed/custom UI | Authentication or quota-identity propagation | Test once on the normal logged-in Hub page |
| Quota falls faster than the visible runtime suggests | Default 60-second request, xlarge, retries, duplicate submissions, or nested Space calls |
Check the Space implementation if available |
| Stop was pressed but work continued | The backend function may already have been running | Do not assume UI cancellation immediately terminates ordinary Python work |
GPU not assigned
There is a recent Forum report describing this sequence:
Waiting for a GPU to become available
→ no worker is assigned
→ "No GPU was available for you"
→ the requested time still appears consumed
That report does not establish a universal root cause, refund rule, or bug by itself. It is still useful because it identifies a more specific boundary than “the generator failed.”
If that was your exact case, include the timestamp and message when reporting it. It may allow Hugging Face or the Space author to distinguish scheduler/allocator failure from an exception inside user code.
The same quota message can represent another limit
In this April 2026 Forum discussion, an HF contributor explained that Free users had both time-based quota and a request-based limit, and that reaching the run limit was temporarily returning the same error as the time quota.
The numerical limit may change, so the durable lesson is:
Do not infer the exact limiting mechanism from the words “quota exceeded” alone.
Authentication and API paths
The Spaces API documentation states that authenticated requests consume the caller’s account quota, while unauthenticated calls use a more restricted shared pool. It also shows how a Space calling another ZeroGPU Space should forward the user’s x-ip-token.
This matters for:
- API clients;
- embedded Spaces;
- third-party frontends;
- custom Gradio frontends;
- one Space calling another Space.
There was also a concrete Gradio bug in which gr.Server custom frontends did not perform the expected ZeroGPU token handshake, causing logged-in users to be treated as unauthenticated. That issue was closed through a related fix, but it demonstrates that browser, API, embed, and custom-frontend paths have not always been equivalent.
Retries and duplicate calls
The same Spaces API guide includes a general retry example. Retries are useful for ordinary transient API errors, but every retry of a ZeroGPU prediction may be a new GPU request and therefore a new reservation, depending on the application.
A user may click once while the client or outer application:
- retries automatically;
- calls multiple internal endpoints;
- submits the request twice;
- calls another ZeroGPU Space;
- permits multiple pending Gradio events.
For a Space that is already returning repeatable errors, repeated retries usually make both the quota loss and the diagnosis worse.
Cancellation is not always termination
Gradio’s event implementation documents that functions which have not started can be cancelled, and iterating generators can be interrupted, but an ordinary function that is already running may be allowed to finish. See the current cancels and trigger_mode documentation in Gradio’s event code.
So closing the tab or pressing Stop does not always prove that the GPU-side function stopped immediately.
Minimal check without burning much more quota
A low-cost test path would be:
- Do not repeatedly retry the same failing Space.
- Use the normal Hugging Face Space page while logged in.
- Save:
- the Space URL;
- the exact error;
- the approximate time and timezone;
- the input options used;
- the quota shown before and after, if visible.
- Note the furthest visible stage:
- immediate quota error;
- waiting for GPU;
- GPU obtained;
- Python/CUDA error;
- inference apparently completed but output failed.
- Test at most one unrelated ZeroGPU Space with a small workload.
- Apply the branch:
- one Space only: report to that Space’s Community;
- multiple unrelated Spaces: report it as a broader ZeroGPU/account/authentication issue;
- API/embed only: compare with the normal authenticated Hub page;
No GPU was available: report it as a scheduler/allocator-stage symptom.
The official ZeroGPU documentation points users to the ZeroGPU Explorers Community for broader feedback.
Useful references
-
Current ZeroGPU documentation
Shared infrastructure, duration, dynamic duration, GPU sizes, quota tiers, and queue priority. -
Hugging Face ZeroGPU implementation guide
Requested duration versus remaining quota,xlarge, call boundaries, worker behavior, and implementation pitfalls. -
How ZeroGPU duration and quota are checked
Default 60-second request, up-front reservation, actual runtime distinction, and quota error modes. -
How ZeroGPU works internally
Main process, temporary/reused GPU workers, model loading, and cold/warm worker behavior. -
Spaces as API endpoints
Authentication, API usage, retries, and forwarding user identity between Spaces. -
A previous failed-session quota question
A closely related user report; the reply is a community explanation rather than an official policy statement. -
Time charged before GPU assignment
A report concerning the scheduler/allocator boundary. -
Time quota versus request-count limit discussion
An example where similar error wording had different underlying causes. -
Proposal for a public remaining-quota API
Closed as not planned; useful context for why users and Space authors cannot always inspect the accounting state precisely.
So the basic behavior you observed is consistent with ZeroGPU’s reservation model, but your UX complaint is still valid: the reservation size, GPU acquisition stage, retry count, and exact failure point are not always visible to the visitor.
For a consistently broken generator, reporting the exact error to its author is more useful than spending another reservation on repeated attempts. For failures across several unrelated Spaces—or a repeated No GPU was available for you sequence—the broader ZeroGPU Community is the better route.