> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blobhub.io/llms.txt
> Use this file to discover all available pages before exploring further.

# blobhub blob limits

> The limits that apply to a blob, including the import allowlist, and the admin key needed to read them

`blob limits` shows the limits in force for a blob — quotas like `revisions_per_blob`, and the
`workflow_component_code_imports` allowlist that decides which third-party modules a revision's code may import.

It is the one command in this group a `read`- or `write`-scoped key cannot run at all, and that single fact
explains behaviour across several other commands. This page is where it is stated.

## Synopsis

```bash theme={null}
blobhub blob limits <org>/<blob> [--refresh]
```

| Argument | Default  | Description                                          |
| -------- | -------- | ---------------------------------------------------- |
| `blob`   | required | Blob as `<org>/<name>`, or a bare name with `--org`. |

| Flag        | Default | Description                                        |
| ----------- | ------- | -------------------------------------------------- |
| `--refresh` | off     | Also refresh the compiler's local allowlist cache. |

## What it does

One call, to the blob's limits route. Unlike its two siblings it never fetches the blob record first — the limits
route is the only request it makes.

```text theme={null}
Limits for acme/dragon-ops
  revisions_per_blob                       actual=12, maximum=50
  workflow_component_code_imports          value=['numpy', 'pandas']
  workflow_definitions_per_revision        actual=4, maximum=100
```

Entries print one per line, sorted by name, with each entry's own fields sorted and rendered as `key=value`.
Numeric limits carry a `maximum`, plus an `actual` where the platform tracks usage; metadata limits such as the
import allowlist carry a `value` instead.

What you get back is the **merged hierarchy**, not just the limits set on the blob: the platform walks from the
blob up through its ancestors and merges them, with the nearest target winning per field. So the set you see is
neither fixed nor exhaustive — it is whatever has been configured for this blob and everything above it.

Under `--json` the payload carries `blob`, `limits`, `refreshed`, and `cache_path` (`null` without `--refresh`).

## Reading limits requires an `admin` key

The limits routes check for the `admin` role. The `read` and `write` keys the platform itself recommends for
automation get a `403`. This was confirmed against the deployed API with a real write key, not inferred from the
handler.

That one fact is the reason for behaviour on several other commands, all of which have to work under exactly the
keys that cannot read limits:

| Where                                           | What the missing `admin` key causes                                                                                                                                                                                                                                                                                                                                                                   |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workflow build`, `diff`, `deploy`              | The live allowlist read `403`s, so the compiler falls back to its local cache. An import it still cannot resolve degrades from the hard failure `IMPORT_UNAVAILABLE` to the `IMPORT_UNVERIFIED` advisory — the build proceeds and tells you it could not verify. `--strict-imports` restores the hard failure on `build` and `deploy`; `diff` has no such flag, since it writes nothing to fail late. |
| [`blobhub blob revisions`](/cli/blob/revisions) | The truncation check compares the returned count against `revisions_per_blob`. Unreadable, so the check never runs and `REVISION_LIST_TRUNCATED` cannot fire.                                                                                                                                                                                                                                         |
| `workflow ls`                                   | The same, against `workflow_definitions_per_revision`, for `DEFINITION_LIST_TRUNCATED`.                                                                                                                                                                                                                                                                                                               |
| `scheduler deploy`                              | Validating a schedule's `target.workflow` alias means confirming the definition listing was complete, which needs the same limit. Without it the check still refuses an alias it cannot find, but says so in a message that names its own uncertainty rather than claiming the definition does not exist.                                                                                             |

**This command does not degrade.** A `403` is a hard `LIMITS_NOT_ACCESSIBLE`, deliberately unlike the compiler's
allowlist read that swallows the same `403` and falls back to cache. The difference is what the caller asked for:
a build wants imports checked, and a cached answer serves that; this command was asked for the limits, and a
partial answer quietly sourced from a week-old file is worse than a clear refusal.

**And it will not name a cause it cannot know.** The same handler answers `403` for a blob it cannot find, so the
message names both possibilities — not an admin key, or no such blob — and asserts neither. Sending someone off
to mint an admin key over a typo'd blob name is a worse failure than saying plainly that the platform conflates
the two.

## `--refresh` and the compiler's allowlist cache

`--refresh` writes the module list from `workflow_component_code_imports` into the cache that `build`, `diff` and
`deploy` fall back on, under `~/.blobhub/cache/allowlist/`, at mode `0600`, alongside the fetch timestamp and the
org and blob it came from. One more line follows the limits, naming the file it wrote:

```text theme={null}
Allowlist cache written to /Users/you/.blobhub/cache/allowlist/acme/dragon-ops.yaml
```

That same path is the `--json` payload's `cache_path`.

A live allowlist read already writes that cache, so a build under an `admin` key refreshes it on its own. The
flag is for when the key that can read limits is **not** the key that runs the build: an operator with an `admin`
key seeds the cache, and later builds under a `write` key read it. The cache is per-machine, so this helps where
the seeding and the building happen on the same machine or in the same image.

Before relying on it, know how the cache is keyed and when it goes stale.

**The cache key is your reference as you typed it**, lower-cased — org-qualified exactly when your reference is.
`build` keys on the manifest's `blob:` field the same way, as written. So a manifest saying `blob: dragon-ops`
reads a different cache entry from the one `blobhub blob limits acme/dragon-ops --refresh` writes, and the
refresh you just ran would change nothing:

```bash theme={null}
# for a manifest whose blob: field is 'dragon-ops', refresh the bare name
blobhub --org acme blob limits dragon-ops --refresh
```

**A cache entry goes stale after seven days.** Past that, a build reading it raises `ALLOWLIST_STALE` and
[`blobhub doctor`](/cli/utilities#blobhub-doctor)'s `allowlist` row warns, naming the entry and its age. This
command is how you clear that.

## Errors

| Code                                                           | When                                                                                                                                                                                                                                                        |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LIMITS_NOT_ACCESSIBLE`                                        | The limits read returned `403`: this key is not `admin`-scoped, or the blob is absent. The platform returns the same `403` for both.                                                                                                                        |
| `BLOB_REFERENCE_INVALID`                                       | The reference is empty, carries more than one `/`, has an empty org before the `/`, has no blob name, or is a bare name with no `--org` and no `BLOBHUB_ORG`.                                                                                               |
| `MANIFEST_INVALID`                                             | `--refresh` only, and despite the name: the reference cannot be turned into a cache-file path. No empty, `.`, `..`, absolute, or backslash-bearing segments. The code is shared with the manifest loader, which is the other caller of the same normalizer. |
| `CREDENTIALS_NOT_FOUND`                                        | No API key from flags, environment, or credentials file.                                                                                                                                                                                                    |
| `PROFILE_NOT_FOUND`                                            | `BLOBHUB_PROFILE` names a profile that is not stored.                                                                                                                                                                                                       |
| `INSECURE_CREDENTIALS_PERMISSIONS`                             | `credentials.yaml` is readable by group or other.                                                                                                                                                                                                           |
| `API_RATE_LIMITED`, `API_TRANSIENT_ERROR`, `API_NETWORK_ERROR` | The limits call failed after its retries.                                                                                                                                                                                                                   |

`BLOB_NOT_ACCESSIBLE` never appears here. This command never fetches the blob record, so an absent blob reaches
you as `LIMITS_NOT_ACCESSIBLE` instead — which is also all the platform said.

## See also

* [`blobhub blob show`](/cli/blob/show) — the record, readable with any key that can see the blob.
* [`blobhub blob revisions`](/cli/blob/revisions) — where `revisions_per_blob` decides whether an advisory can fire.
* [Concepts](/cli/concepts) — the allowlist and the three other platform behaviours that shape the binary.
* [Error codes](/cli/error-codes) — `LIMITS_NOT_ACCESSIBLE`, the allowlist advisories, and the rest of the catalog.
* [Get Blob Limits](/rest-api/blobs/get-limits) — the route behind this command.
