> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.ampdb.io/api/mcp` to find what you need.

# ampctl dataset

`ampctl dataset` publishes and runs [datasets](/get-started/concepts/datasets). You register a dataset's
[manifest](/datasets/manifests), the file that defines its tables, under a name and a version. Then you deploy that
version, so a [worker](/managing-amp/workers) writes its tables, and you follow its progress or stop it.
The usual loop is `register`, then `deploy`, then `status`. [Managing Datasets](/managing-amp/datasets) walks through
it; this page documents each command.

| Command                                                          | What it does                                                      |
| ---------------------------------------------------------------- | ----------------------------------------------------------------- |
| [`register`](/clis/ampctl/dataset#ampctl-dataset-register)                           | Publishes a manifest under a dataset's name, and tags a version.  |
| [`deploy`](/clis/ampctl/dataset#ampctl-dataset-deploy)                               | Starts writing a version's tables.                                |
| [`status`](/clis/ampctl/dataset#ampctl-dataset-status)                               | Shows a deployment's status, progress, and error.                 |
| [`events`](/clis/ampctl/dataset#ampctl-dataset-events)                               | Lists what happened to a deployment, and when.                    |
| [`stop`](/clis/ampctl/dataset#ampctl-dataset-stop)                                   | Stops a deployment, keeping the data it wrote.                    |
| [`list`](/clis/ampctl/dataset#ampctl-dataset-list)                                   | Lists the registered datasets.                                    |
| [`list materialized`](/clis/ampctl/dataset#ampctl-dataset-list-materialized)         | Lists the jobs of every deployment.                               |
| [`inspect`](/clis/ampctl/dataset#ampctl-dataset-inspect)                             | Shows a version's tags, kind, manifest hash, and tables.          |
| [`versions`](/clis/ampctl/dataset#ampctl-dataset-versions)                           | Lists a dataset's versions.                                       |
| [`versions materialized`](/clis/ampctl/dataset#ampctl-dataset-versions-materialized) | Lists the jobs of one dataset's deployments.                      |
| [`manifest`](/clis/ampctl/dataset#ampctl-dataset-manifest)                           | Prints a version's manifest.                                      |
| [`remove`](/clis/ampctl/dataset#ampctl-dataset-remove)                               | Removes a dataset, or one of its version tags.                    |
| [`restore`](/clis/ampctl/dataset#ampctl-dataset-restore)                             | Rebuilds Amp's records of a version's tables from object storage. |

## Prerequisites

* A running Amp, like the one the [Quickstart](/get-started/quickstart) starts with [solo mode](/running-amp/solo-mode).
* `ampctl`, [installed](/clis/ampctl#install) and [connected to it](/clis/ampctl#connect-to-amp).
* For the examples, the Quickstart's [provider](/providers) `mainnet_rpc` and
  [raw dataset](/datasets/raw-datasets) `acme/eth_mainnet@1.0.0`, which extracts Ethereum blocks 24,000,000 to
  24,000,099 through it, and the [derived dataset](/datasets/derived-datasets#the-erc-20-transfers-dataset)
  `acme/eth_transfers@1.0.0`, which you create on top of it, and which keeps the ERC-20 transfers from those blocks.
  The examples that register a manifest run in the directory that holds `eth_mainnet.json` and `eth_transfers.json`.

Every command also takes the [global flags](/clis/ampctl#global-flags): `--admin-url`, `--auth-token`, and `--json`,
which prints the result as [JSON](/clis/ampctl#json-output). `ampctl datasets` is the same command as `ampctl dataset`.
A command that fails prints its error on stderr and exits with a nonzero [exit code](/clis/ampctl#exit-codes): `2` when
an argument is invalid, and `1` otherwise.

## Names and references

Commands name a dataset in one of two ways:

* **A name**, `namespace/name`, like `acme/eth_mainnet`. `register`, `versions`, and `remove` take one. The namespace
  holds lowercase letters, digits, and underscores. So does the name, which starts with a letter or an underscore.
* **A reference**, `namespace/name@revision`, like `acme/eth_mainnet@1.0.0`, which names one version of the dataset. The
  other commands take one.

The revision after the `@` is one of:

* A version tag, like `1.0.0`: a [semantic version](https://semver.org) you give a manifest when you register it.
* `latest`: the dataset's highest version tag.
* `dev`: the manifest registered most recently, with or without a tag.
* A manifest hash: the 64-character hexadecimal hash that identifies a manifest by its content, which `register` and
  `inspect` print.

Amp resolves each revision to a manifest hash, so while `1.0.0` is the highest version, `acme/eth_transfers@latest` and
`acme/eth_transfers@1.0.0` name the same thing, down to the same deployment. [Versioning](/datasets/versioning) explains
how tags move. A reference can also be written as a package URL, like `pkg:amp/acme/eth_mainnet@1.0.0`.

The revision is required, even where a command's help says it defaults to `latest`:

```
error: invalid value 'acme/eth_transfers' for '<REFERENCE>': invalid reference format 'acme/eth_transfers', missing '@' separator for revision
```

A name with other characters fails before anything is sent.

### Deployments

Deploying a version starts a *deployment*, which Amp also calls a materialized dataset. It's three
[jobs](/managing-amp/jobs): one for the deployment as a whole, which the controller runs; one that a worker runs to
write the tables; and one that a worker runs every hour to [delete the files](/running-amp/storage/garbage-collection)
the tables no longer use. `deploy` prints the ID of the first. `status`, `events`, and `stop` find the
deployment by its reference, so you don't need the ID; the [`ampctl job`](/clis/ampctl/job) commands take it.

A version has one deployment. Deploying it again while it runs changes nothing. Once it has ended, by completing,
stopping, or failing for good, deploying it again restarts the same jobs, under the same ID, with the settings you pass
that time. Its tables keep what they hold, so it carries on from the last block written. Each status a job goes through,
like `SCHEDULED`, `RUNNING`, `ERROR`, `COMPLETED`, `STOPPED`, or `FATAL`, is explained in
[Job Lifecycle](/managing-amp/jobs/lifecycle).

## `ampctl dataset register`

Publishes a manifest under a dataset's name, and tags a version of it.

```
ampctl dataset register [OPTIONS] NAMESPACE/NAME FILE_OR_HASH
```

| Argument / flag     | Type                        | Default  | Description                                                                                                       |
| ------------------- | --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `NAMESPACE/NAME`    | string                      | required | The dataset's [name](/clis/ampctl/dataset#names-and-references), like `acme/eth_transfers`. A name that doesn't exist yet is created. |
| `FILE_OR_HASH`      | path, URL, or manifest hash | required | The manifest. See [`FILE_OR_HASH`](/clis/ampctl/dataset#file_or_hash).                                                                |
| `-t`, `--tag <TAG>` | semantic version            | none     | The version to tag, like `--tag 1.0.0`. Without it, only `dev` moves to the manifest.                             |
| `--deploy`          | flag                        | off      | Deploys the version once it's registered. See [`--deploy`](/clis/ampctl/dataset#--deploy).                                            |

Its alias is `ampctl dataset reg`.

`register` checks the manifest, stores it, and links it to the dataset. Then it moves `dev` to the manifest and, with
`--tag`, tags the manifest with that version, which also moves `latest` when it's the dataset's highest version. Amp
checks a derived dataset's SQL against its dependencies, which must already be registered.

:::terminal
```bash
ampctl dataset register acme/eth_transfers ./eth_transfers.json --tag 1.0.0
```

```
✓ Dataset registered successfully
→ Namespace: acme
→ Name: eth_transfers
→ Version: 1.0.0
→ Hash: fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26
→ Kind: manifest
→ Start block: 0
→ Finalized only: false
→ Tables: transfers
```
:::

`Kind` is `manifest` for a derived dataset, and the provider kind, like `evm-rpc`, for a raw one. `Start block` is the
first block a raw dataset extracts; a derived dataset reports `0`. `Finalized only` is whether it extracts only
[finalized](/get-started/concepts/reorgs) blocks.

Amp stores each manifest once, under its hash, so registering the same file again changes nothing and prints the same
result. A changed file is a new manifest with a new hash, so register it under a new version, like `1.1.0`. Tagging it
with a version that already exists moves that tag to the new manifest, without a warning. The version's deployment stays
with the old manifest, which you then reach by its hash.

Without `--tag`, the output has no `Version` line. With `--json`:

```json
{
  "namespace": "acme",
  "name": "eth_transfers",
  "version": "1.0.0",
  "manifest_hash": "fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26",
  "kind": "manifest",
  "start_block": 0,
  "finalized_blocks_only": false,
  "tables": ["transfers"]
}
```

### `FILE_OR_HASH`

The manifest to register:

* **A file**: a local path, or a `file://`, `s3://`, `gs://`, or `az://` URL. `ampctl` reads it, with the credentials in
  its environment for object storage, like `AWS_ACCESS_KEY_ID`, and sends it to Amp.
* **A manifest hash**: the 64-character hash of a manifest Amp already has, like one another dataset or version uses.
  Nothing is uploaded. To register a file whose name is 64 hexadecimal characters, write it as `./` followed by the
  name.

Tagging a manifest that's already registered, by its hash, is how you give a version a second tag:

```bash
ampctl dataset register acme/eth_transfers fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26 --tag 1.0.1
```

### `--deploy`

Deploys the version right after registering it, like running [`deploy`](/clis/ampctl/dataset#ampctl-dataset-deploy) with no flags: it syncs
continuously, with no end block, and with every other setting at its default. With `--tag`, it deploys that version;
without it, it deploys the manifest by its hash. For any other setting, run `deploy` instead.

```bash
ampctl dataset register acme/eth_transfers ./eth_transfers.json --deploy
```

Here, `eth_transfers.json` is still the manifest of `1.0.0`, so this restarts the [deployment](/clis/ampctl/dataset#deployments) of `1.0.0`,
job 4, which now keeps running, with no end block. With `--json`, the result has the deployment's `job_id`:

```json
{
  "namespace": "acme",
  "name": "eth_transfers",
  "manifest_hash": "fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26",
  "kind": "manifest",
  "start_block": 0,
  "finalized_blocks_only": false,
  "tables": ["transfers"],
  "job_id": 4
}
```

If the deployment fails, the manifest stays registered, and `register` fails with
`dataset registered but deployment failed`, followed by one of [`deploy`](/clis/ampctl/dataset#ampctl-dataset-deploy)'s errors.

### Errors

* `error: invalid value './missing.json' for '<FILE_OR_HASH>': invalid manifest file path: ./missing.json`: there's no
  file at that local path. Check the path.
* `✗ manifest file not found: file:///Users/you/missing.json/`: there's no file at that URL.
* `✗ invalid manifest format`, followed by where the JSON stops being valid, like `expected ident at line 1 column 2`:
  the file isn't JSON.
* `error: invalid value 'latest' for '--tag <TAG>': unexpected character 'l' while parsing major version number`: the
  tag isn't a semantic version. `latest` and `dev` move on their own, and `v1` needs to be `1.0.0`.
* `MANIFEST_VALIDATION_ERROR: Manifest validation error: Dependency 'eth' not found (acme/eth_mainnet@2.0.0)`, after
  `✗ dataset registration failed`: a dependency of the derived dataset isn't registered. Register it first, or fix the
  reference in the manifest's `dependencies`.
* `MANIFEST_VALIDATION_ERROR: Manifest validation error: Failed to plan query for table 'transfers'`, followed by the
  reason: a table's SQL doesn't run against its dependencies, like when it reads a table its dependency doesn't have.
  Registering stops at the first table that fails. [Derived Datasets](/datasets/derived-datasets) explains what Amp
  checks.
* `unexpected response (status 404): {"error_code":"MANIFEST_NOT_FOUND",…}`: no registered manifest has that hash.

## `ampctl dataset deploy`

Starts writing a version's tables: extracting a raw dataset's blocks through its provider, or computing a derived
dataset's tables from its dependencies.

```
ampctl dataset deploy [OPTIONS] NAMESPACE/NAME@REVISION
```

| Argument / flag                                    | Type                             | Default               | Description                                                                                                  |
| -------------------------------------------------- | -------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------ |
| `NAMESPACE/NAME@REVISION`                          | string                           | required              | The version to deploy, like `acme/eth_mainnet@1.0.0`. See [Names and references](/clis/ampctl/dataset#names-and-references).     |
| `--end-block <END_BLOCK>`                          | integer                          | none                  | The last block to write, like `--end-block 24000099`. See [`--end-block`](/clis/ampctl/dataset#--end-block-end_block).           |
| `--parallelism <PARALLELISM>`                      | integer, 1 to 65535              | `1`                   | How many extractions run at once, like `--parallelism 4`. See [`--parallelism`](/clis/ampctl/dataset#--parallelism-parallelism). |
| `--worker-id <WORKER_ID>`                          | string                           | the controller picks  | The worker to run it on, like `--worker-id worker`. See [`--worker-id`](/clis/ampctl/dataset#--worker-id-worker_id).             |
| `--verify <ENCODING>`                              | `ethereum` or `solana`           | none                  | Checks the data against the chain's hashes, like `--verify ethereum`. See [`--verify`](/clis/ampctl/dataset#--verify-encoding).  |
| `--provider <PROVIDER>`                            | string                           | any matching provider | The only provider to extract from, like `--provider mainnet_rpc`. See [`--provider`](/clis/ampctl/dataset#--provider-provider).  |
| `--backfill-strategy <STRATEGY>`                   | `archive-then-rpc` or `rpc-only` | `archive-then-rpc`    | Where past blocks come from. See [`--backfill-strategy`](/clis/ampctl/dataset#--backfill-strategy-strategy).                     |
| `--retry-strategy` and the other `--retry-*` flags | see [Retry flags](/clis/ampctl/dataset#retry-flags)  | Amp's default         | How a failing deployment is retried.                                                                         |

Its alias is `ampctl dataset dep`.

:::terminal
```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000099
```

```
✓ Dataset deployed successfully
→ Job ID: 1
```
:::

The command returns once the deployment is scheduled, and a worker starts it right away. Follow it with
[`status`](/clis/ampctl/dataset#ampctl-dataset-status). With `--json`, the result is the ID:

```json
{ "job_id": 1 }
```

While the deployment runs, deploying the version again prints the same ID and ignores the flags you pass. To change its
settings, [stop](/clis/ampctl/dataset#ampctl-dataset-stop) it first. Once it has ended, deploying the version again restarts it with the
flags you pass this time; a setting you leave out goes back to its default. So a deployment that completed at its
end block carries on to a later one:

```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000999
```

### `--end-block <END_BLOCK>`

The last block the deployment writes. Once it has written it, it completes, with the status `COMPLETED`.

* **Type**: a block number. Anything else, like `latest`, fails with `invalid digit found in string`.
* **Default**: none: the deployment keeps up with the chain, writing new blocks as they're produced, and never completes

A raw dataset starts at the start block of its manifest. A derived dataset writes as far as its dependencies have
written, up to this block.

### `--parallelism <PARALLELISM>`

How many block extractions a [Solana](/providers/solana) dataset runs at once. More extractions finish a long range
sooner, but send the provider more requests at once, so a provider with a rate limit may answer some with errors. From
the archive, it's how many parts of an epoch's file Amp reads at once. With `1`, Amp reads each epoch from its first
slot. With more, it first reads the file's index, which takes minutes, then only the parts the range needs (see
[Old Faithful archive](/providers/solana#old-faithful-archive)).

* **Type**: an integer from 1 to 65535
* **Default**: `1`
* **Applies to**: `solana` datasets, and the writers of a [Phaser](/providers/phaser) dataset. Every other dataset
  accepts it and ignores it: `evm-rpc` datasets, for one, extract up to eight blocks at once whatever you pass.
* **Alias**: `--concurrency`, which the help doesn't list

```bash
ampctl dataset deploy acme/solana_mainnet@1.0.0 --parallelism 4
```

### `--worker-id <WORKER_ID>`

The worker that runs the deployment, by the node ID [`ampctl worker list`](/clis/ampctl/worker#ampctl-worker-list)
prints. A trailing `*` matches each worker whose node ID starts with what comes before it, like `worker-*`, and Amp
picks one of them at random.

* **Type**: a node ID, or a prefix followed by `*`
* **Default**: the worker the controller is configured to use, or else one it picks at random

The worker must be running: it must have sent a heartbeat in the last 5 seconds. Solo mode runs one worker, named
`worker`.

```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000999 --worker-id worker
```

### `--verify <ENCODING>`

Checks each block against the chain's own hashes and signatures as it's extracted, so a provider can't serve altered
data unnoticed. A block that fails the check fails the attempt, which is [retried](/clis/ampctl/dataset#retry-flags). See
[Verification](/managing-amp/verification).

* **Type**: `ethereum`, which checks block hashes, transaction roots, and receipt roots, or `solana`, which checks block
  hashes and transaction signatures
* **Default**: none: nothing is checked
* **Applies to**: raw datasets. A derived or Phaser dataset rejects it.

```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000999 --verify ethereum
```

### `--provider <PROVIDER>`

Pins the deployment to one registered [provider](/providers), by name. Without it, a raw dataset uses every provider
registered for its kind and network, and moves to the next one each time an attempt fails. With it, the deployment uses
that provider alone and never falls back to another.

* **Type**: a provider's name, like `mainnet_rpc`
* **Default**: none: any provider registered for the dataset's kind and network
* **Applies to**: raw datasets. A derived or Phaser dataset rejects it.

```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000999 --provider mainnet_rpc
```

`deploy` doesn't check the name. If no provider of that name is registered for the dataset's kind and network, the
deployment starts, then fails with `PINNED_PROVIDER_NOT_FOUND` and is retried, as [`status`](/clis/ampctl/dataset#ampctl-dataset-status)
shows. Register the provider, or [stop](/clis/ampctl/dataset#ampctl-dataset-stop) the deployment and deploy it again with the right name.

### `--backfill-strategy <STRATEGY>`

Where a raw dataset gets the blocks produced before it was deployed. Some providers have an archive, a bulk copy of the
chain's history that's faster to read than requesting each block over RPC. The archive trails the chain, so the end of
the range, and every block after it, always comes over RPC.

* **Type**: `archive-then-rpc`, which reads the archive first and the rest over RPC, or `rpc-only`, which reads
  everything over RPC
* **Default**: `archive-then-rpc`
* **Applies to**: raw datasets. Only the [Solana provider](/providers/solana) has an archive; every other provider reads
  over RPC whatever you pass. A derived or Phaser dataset rejects it.

Amp v0.0.42 can't read Solana's archive from epoch 1064 on: deploy those slots with `rpc-only` (see
[Old Faithful archive](/providers/solana#old-faithful-archive)).

```bash
ampctl dataset deploy acme/solana_mainnet@1.0.0 --backfill-strategy rpc-only
```

### Retry flags

When an attempt fails with an error that may go away, like a provider timing out, Amp retries it after a delay. By
default, it retries until you stop the deployment, and the delay doubles after each failure, up to an hour. These flags
replace that [retry strategy](/managing-amp/jobs/retries), which explains each part.

| Flag                                              | Type                                                 | Default                | Description                                                                                                                                                                   |
| ------------------------------------------------- | ---------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--retry-strategy <RETRY_STRATEGY>`               | `none`, `bounded`, or `unless_stopped`               | Amp's default          | `none` fails for good on the first error. `bounded` fails for good once `--retry-max-attempts` failures happen within `--retry-window-secs`. `unless_stopped` never gives up. |
| `--retry-max-attempts <RETRY_MAX_ATTEMPTS>`       | integer, at least 1                                  | required for `bounded` | How many failures within the window end the deployment, like `--retry-max-attempts 5`. Only with `bounded`.                                                                   |
| `--retry-window-secs <RETRY_WINDOW_SECS>`         | integer, 1 to 604800 (7 days)                        | `3600`                 | The window, in seconds, that failures are counted in. Older failures stop counting. Only with `bounded`.                                                                      |
| `--retry-backoff <RETRY_BACKOFF>`                 | `fixed`, `exponential`, or `exponential_with_jitter` | `exponential`          | How the delay grows: `fixed` waits the base delay each time, `exponential` multiplies it after each failure, and `exponential_with_jitter` adds up to a quarter at random.    |
| `--retry-base-delay-secs <RETRY_BASE_DELAY_SECS>` | integer, at least 1                                  | `1`                    | The first delay, in seconds, like `--retry-base-delay-secs 10`.                                                                                                               |
| `--retry-multiplier <RETRY_MULTIPLIER>`           | number, more than 0                                  | `2.0`                  | What each delay is multiplied by, like `--retry-multiplier 1.5`. Only for exponential backoff.                                                                                |
| `--retry-max-delay-secs <RETRY_MAX_DELAY_SECS>`   | integer, at least the base delay                     | none                   | The longest delay, in seconds, like `--retry-max-delay-secs 300`. Without it, an exponential backoff you set has no cap, unlike Amp's default.                                |

The other flags need `--retry-strategy`, and the backoff flags need `bounded` or `unless_stopped`:

```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000999 --retry-strategy bounded --retry-max-attempts 5 --retry-max-delay-secs 300
```

[`list materialized`](/clis/ampctl/dataset#ampctl-dataset-list-materialized) shows the strategy each of a deployment's jobs has, with
each value it left at its default:

```
Retry Strategy
  Strategy    : bounded
  Max Attempts : 5
  Failure Window : 3600s
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 300s
  Multiplier  : x2
```

### Errors

`deploy` checks its flags before sending anything, and Amp checks the version and the worker before scheduling it:

* `✗ dataset 'acme/eth_transfers@2.0.0' not found`: the dataset or the version isn't registered. Check it with
  [`versions`](/clis/ampctl/dataset#ampctl-dataset-versions).
* `unexpected response (status 400): {"error_code":"UNSUPPORTED_OPTION","error_message":"option 'verify' is not supported for 'manifest' datasets"}`,
  after `✗ failed to deploy dataset`: a flag doesn't apply to the dataset's kind. Here, `--verify` was passed for a
  derived (`manifest`) dataset. Drop it.
* `WORKER_NOT_AVAILABLE: Failed to schedule job: specified worker 'worker-2' not found or inactive`: no running worker
  has that node ID. Check the IDs [`ampctl worker list`](/clis/ampctl/worker#ampctl-worker-list) prints.
* `SCHEDULER_ERROR: Failed to schedule job: no active workers match pattern 'worker-*'`: no running worker's node ID
  starts with that prefix.
* `unexpected response (status 404): {"error_code":"DEPENDENCY_NOT_FOUND","error_message":"Dependency 'eth' not found (acme/eth_mainnet@1.0.0)"}`:
  a dependency of the derived dataset was [removed](/clis/ampctl/dataset#ampctl-dataset-remove). Register it again.
* `✗ invalid retry strategy arguments`, followed by what's wrong, like
  `--retry-max-attempts is required when --retry-strategy=bounded`: the retry flags don't fit together. See
  [Retry flags](/clis/ampctl/dataset#retry-flags).
* `error: invalid value '0' for '--parallelism <PARALLELISM>': number would be zero for non-zero type`, and the like: a
  flag's value is out of its range, or isn't one of its values.

A deployment can also start and then fail, which [`status`](/clis/ampctl/dataset#ampctl-dataset-status) shows. One case to know: a derived
dataset deployed again with an end block its tables already reach fails for good, with the status `FATAL` and
`start block (24000100) is greater than end block (24000099)`. Its tables are complete; to write more, deploy it with a
later end block.

## `ampctl dataset status`

Shows a deployment's status, how far it has written each table, and its error when it's failing.
[Dataset Status](/managing-amp/dataset-status) explains how to read each part.

```
ampctl dataset status NAMESPACE/NAME@REVISION
```

| Argument                  | Type   | Default  | Description                                          |
| ------------------------- | ------ | -------- | ---------------------------------------------------- |
| `NAMESPACE/NAME@REVISION` | string | required | The deployed version, like `acme/eth_mainnet@1.0.0`. |

:::terminal
```bash
ampctl dataset status acme/eth_mainnet@1.0.0
```

```
ID:              1
Status:          COMPLETED
Kind:            Raw
Dataset:         acme/eth_mainnet@1.0.0
tables:
  blocks:
    files_count: 1
    total_size_bytes: 63.25 KiB
    networks:
      mainnet:
        start_block: 24000000
        current_block: 24000099
        block_timestamp: 1765585559
        delay_seconds: 28055619s (46 weeks)
        end_block: 24000099
  logs:
    files_count: 1
    total_size_bytes: 2.15 MiB
    networks:
      mainnet:
        start_block: 24000000
        current_block: 24000099
        block_timestamp: 1765585559
        delay_seconds: 28055619s (46 weeks)
        end_block: 24000099
  transactions:
    files_count: 1
    total_size_bytes: 4.08 MiB
    networks:
      mainnet:
        start_block: 24000000
        current_block: 24000099
        block_timestamp: 1765585559
        delay_seconds: 28055619s (46 weeks)
        end_block: 24000099
```
:::

| Field                                    | Description                                                                                                       |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `ID`                                     | The deployment's job ID, which `deploy` printed.                                                                  |
| `Status`                                 | The deployment's status as a whole. See [Failing deployments](/clis/ampctl/dataset#failing-deployments).                              |
| `Kind`                                   | `Raw`, `Derived`, or `Phaser`. `(unknown)` until the deployment has written something.                            |
| `files_count`, `total_size_bytes`        | How many Parquet files the table has, and their size.                                                             |
| `start_block`                            | The first block of the table. For a derived table, `networks` names its chains instead.                           |
| `current_block`                          | The last block written. Tables are written in batches, so it moves in steps.                                      |
| `block_timestamp`, `watermark_timestamp` | When the last block written was produced, in seconds since 1970 (UTC).                                            |
| `delay_seconds`                          | How long ago that was: how far the table is behind the chain. These blocks are from December 2025, so it's large. |
| `end_block`                              | The [end block](/clis/ampctl/dataset#--end-block-end_block) the deployment stops at.                                                  |

Before a deployment has written its first file, `Progress: (nothing written yet)` replaces `tables`. The same happens
to a dataset with data once
[another dataset with the same manifest](/managing-amp/datasets#register-a-manifest-under-a-second-name) is deployed.

A derived table reports its progress in one block:

```
tables:
  transfers:
    delay_seconds: 28055619s (46 weeks)
    files_count: 1
    total_size_bytes: 518.91 KiB
    watermark_timestamp: 1765585559
    networks:
      "mainnet"
```

With `--json`, the status is under `status`, and also has the IDs of the deployment's other two jobs, its idempotency
key, and sizes in bytes. `materialization` is the job that writes the tables, with its own `status` and `progress`, and
`garbage_collection` is the job that deletes unused files, with how many are waiting to be deleted:

:::terminal
```bash
ampctl dataset status acme/eth_mainnet@1.0.0 --json | jq '.status | {status, writer: .materialization.status, gc: .garbage_collection.status}'
```

```json
{
  "status": "COMPLETED",
  "writer": "COMPLETED",
  "gc": "COMPLETED"
}
```
:::

### Failing deployments

When an attempt fails and is retried, the deployment's `Status` stays `RUNNING`, and an `Error detail` block shows the
last error. Here, the deployment was pinned to a provider named `mainnet`, which isn't registered, with
`ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000199 --provider mainnet`:

:::terminal
```bash
ampctl dataset status acme/eth_mainnet@1.0.0
```

```
ID:              1
Status:          RUNNING
Kind:            Raw
Dataset:         acme/eth_mainnet@1.0.0
tables:
…
Error detail:
  error_code: PINNED_PROVIDER_NOT_FOUND
  error_message: Pinned provider 'mainnet' not found for kind 'evm-rpc' and network 'mainnet'
  error_context:
    attempt_index: 3
    dataset: acme/eth_mainnet
    manifest_hash: b9e2ebd92c0752ba8a61a233f9cc5d3f4f8b601b1b789a882a5dd8ece9bca56b
```
:::

To tell a healthy deployment from one that keeps failing, read the status of the job that writes the tables, which is
`ERROR` between attempts:

:::terminal
```bash
ampctl dataset status acme/eth_mainnet@1.0.0 --json | jq -r '.status.materialization.status'
```

```
ERROR
```
:::

When the error is permanent, or the [retry strategy](/clis/ampctl/dataset#retry-flags) gives up, `Status` becomes `FATAL`. Either way, fix
the cause, then [stop](/clis/ampctl/dataset#ampctl-dataset-stop) the deployment if it's still running, and
[deploy](/clis/ampctl/dataset#ampctl-dataset-deploy) it again, with the right settings if a setting is the cause.

### Errors

* `✗ materialized dataset not found: acme/eth_transfers@1.1.0`: the version is registered, but was never deployed.
  [Deploy](/clis/ampctl/dataset#ampctl-dataset-deploy) it.
* `✗ dataset not found: acme/eth_transfers@9.9.9`: the dataset or the version isn't registered.

## `ampctl dataset events`

Lists everything that happened to a deployment's jobs, like being scheduled, starting, failing, and completing, in the
order it happened, with the node that recorded each event.

```
ampctl dataset events [OPTIONS] NAMESPACE/NAME@REVISION
```

| Argument                  | Type   | Default  | Description                                          |
| ------------------------- | ------ | -------- | ---------------------------------------------------- |
| `NAMESPACE/NAME@REVISION` | string | required | The deployed version, like `acme/eth_mainnet@1.0.0`. |

:::terminal
```bash
ampctl dataset events acme/eth_mainnet@1.0.0
```

```
Materialization events for dataset: acme/eth_mainnet@1.0.0

Jobs:
  1  composite        1f88bf7bcbcf5172888c5833dec8d43bb6768c5fed1985c1e79fda5c9cc91410
  2  materialize-raw  23f6d8595cb00fd128311d930159118ec3f8c3a1e1f075754ddcee4ae8776889
  3  gc               2417400af0fd460657deccf08b59ec3184be13d24facd97d3786c64de3f991e7

Events:
  [1] 2026-11-02T17:38:35.762861+00:00 - SCHEDULED (job: 1/composite, node: controller)
  [2] 2026-11-02T17:38:35.762861+00:00 - SCHEDULED (job: 2/materialize-raw, node: worker)
  [3] 2026-11-02T17:38:35.762861+00:00 - SCHEDULED (job: 3/gc, node: worker)
  [4] 2026-11-02T17:38:35.773022+00:00 - RUNNING (job: 1/composite, node: controller)
  [5] 2026-11-02T17:38:35.777546+00:00 - RUNNING (job: 2/materialize-raw, node: worker)
  [6] 2026-11-02T17:38:35.786673+00:00 - RUNNING (job: 3/gc, node: worker)
  [7] 2026-11-02T17:38:35.791522+00:00 - COMPLETED (job: 3/gc, node: worker)
  [8] 2026-11-02T17:38:57.027372+00:00 - COMPLETED (job: 2/materialize-raw, node: worker)
  [9] 2026-11-02T17:38:57.964791+00:00 - COMPLETED (job: 1/composite, node: controller)
```
:::

`Jobs` lists the deployment's three jobs, with their IDs, their kinds, and their idempotency keys:

* `composite`: the deployment as a whole, which the controller runs (`node: controller`). Its ID is the one `deploy`
  prints.
* `materialize-raw`, `materialize-derived`, or `materialize-phaser`: the job that writes the tables.
* `gc`: the job that deletes the files the tables no longer use. It runs every hour, so it completes, then is scheduled
  again.

Each event has its ID, its time, its type, which is the status the job moved to, the job, and the node that recorded it.
Event IDs are shared by every job in Amp, so a deployment's events skip the IDs of other jobs' events. Since deploying a
version again restarts the same jobs, the list holds every deployment of the version, oldest first. A failing deployment
has an `ERROR` event per failed attempt, each followed by `SCHEDULED` and `RUNNING` when it's retried.

With `--json`, the jobs are under `jobs`, each with its `job_id`, `kind`, and `idempotency_key`, and the events under
`events`:

:::terminal
```bash
ampctl dataset events acme/eth_mainnet@1.0.0 --json | jq '.events[0]'
```

```json
{
  "id": 1,
  "job_id": 1,
  "created_at": "2026-11-02T17:38:35.762861+00:00",
  "node_id": "controller",
  "event_type": "SCHEDULED"
}
```
:::

It fails like [`status`](/clis/ampctl/dataset#ampctl-dataset-status): `materialized dataset not found` for a version that was never
deployed, and `dataset not found` for one that isn't registered.

## `ampctl dataset stop`

Stops a deployment. Its tables keep the data it wrote, and queries keep reading them.

```
ampctl dataset stop [OPTIONS] NAMESPACE/NAME@REVISION
```

| Argument                  | Type   | Default  | Description                                          |
| ------------------------- | ------ | -------- | ---------------------------------------------------- |
| `NAMESPACE/NAME@REVISION` | string | required | The deployed version, like `acme/eth_mainnet@1.0.0`. |

To try it on the Quickstart's dataset, which has completed, first deploy it to a later end block, so it runs for a few
minutes:

```bash
ampctl dataset deploy acme/eth_mainnet@1.0.0 --end-block 24000999
ampctl dataset stop acme/eth_mainnet@1.0.0
```

`stop` asks the deployment's jobs to stop, and returns without waiting for them. Their status goes from
`STOP_REQUESTED` to `STOPPING` to `STOPPED`, usually within a few seconds, as [`status`](/clis/ampctl/dataset#ampctl-dataset-status) and
[`events`](/clis/ampctl/dataset#ampctl-dataset-events) show:

```
  [36] 2026-11-02T17:39:46.986984+00:00 - STOP_REQUESTED (job: 1/composite, node: controller)
  [37] 2026-11-02T17:39:48.003308+00:00 - STOP_REQUESTED (job: 2/materialize-raw, node: worker)
  [38] 2026-11-02T17:39:48.003308+00:00 - STOP_REQUESTED (job: 3/gc, node: worker)
  [39] 2026-11-02T17:39:48.012394+00:00 - STOPPING (job: 1/composite, node: controller)
  [40] 2026-11-02T17:39:48.012606+00:00 - STOPPING (job: 2/materialize-raw, node: worker)
  [41] 2026-11-02T17:39:48.018699+00:00 - STOPPING (job: 3/gc, node: worker)
  [42] 2026-11-02T17:39:48.021699+00:00 - STOPPED (job: 3/gc, node: worker)
  [43] 2026-11-02T17:39:48.171376+00:00 - STOPPED (job: 2/materialize-raw, node: worker)
  [44] 2026-11-02T17:39:49.025338+00:00 - STOPPED (job: 1/composite, node: controller)
```

To start it again, [deploy](/clis/ampctl/dataset#ampctl-dataset-deploy) it, with every flag it needs: a setting you leave out goes back to
its default. A deployment reads its [provider](/providers)'s configuration once, when it starts, so stop it and deploy
it again after you change the provider, like its URL. Stopping a deployment that has ended, or a version that was never
deployed, changes nothing and succeeds, with the same message. A deployment that has reached its end block keeps its
garbage collection job running every hour, so stop that job with [`ampctl job stop`](/clis/ampctl/job#ampctl-job-stop).
With `--json`, it prints the reference:

```json
{ "dataset_ref": "acme/eth_mainnet@1.0.0" }
```

A version that isn't registered fails with `✗ dataset not found: acme/eth_transfers@9.9.9`.

## `ampctl dataset list`

Lists the registered datasets, with how many version tags each has.

```
ampctl dataset list [OPTIONS]
```

It takes no arguments. `ampctl dataset ls` is the same command.

:::terminal
```bash
ampctl dataset list
```

```
Datasets:
  acme/eth_mainnet - 1 version(s)
  acme/eth_transfers - 2 version(s)
```
:::

With no datasets registered, it prints `No datasets found`. With `--json`, each dataset has its latest version and every
version tag:

```json
{
  "datasets": [
    { "namespace": "acme", "name": "eth_mainnet", "latest_version": "1.0.0", "versions": ["1.0.0"] },
    { "namespace": "acme", "name": "eth_transfers", "latest_version": "1.0.1", "versions": ["1.0.1", "1.0.0"] }
  ]
}
```

## `ampctl dataset list materialized`

Lists the [jobs](/clis/ampctl/dataset#deployments) of every dataset's deployments, newest first, with their status and settings. By
default, it lists the jobs that haven't ended, so it shows what's running.

```
ampctl dataset list materialized [OPTIONS]
```

| Flag                      | Type               | Default  | Description                                                                             |
| ------------------------- | ------------------ | -------- | --------------------------------------------------------------------------------------- |
| `-s`, `--status <STATUS>` | string             | `active` | Which jobs to list, by status, like `--status all`. See [`--status`](/clis/ampctl/dataset#--status-status). |
| `-l`, `--limit <LIMIT>`   | integer, 1 to 1000 | `50`     | How many jobs to list, like `--limit 10`.                                               |
| `--last-id <LAST_ID>`     | integer            | none     | Lists the jobs older than this job ID, like `--last-id 4`, to read the next page.       |

Here, it shows the deployment from [Failing deployments](/clis/ampctl/dataset#failing-deployments), which is being retried, and the one
[`--deploy`](/clis/ampctl/dataset#--deploy) restarted, which runs with no end block:

:::terminal
```bash
ampctl dataset list materialized
```

```
Materialized Datasets
────────────────────────────────────
Job ID        : 5
Dataset       : acme/eth_transfers
Manifest Hash : fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26
Status        : RUNNING
Node          : worker
End Block     : none
Kind          : materialize-derived
Created At    : 2026-11-02 17:39 UTC
Updated At    : 2026-11-02 17:39 UTC
Trigger       : one_shot
Retry Strategy
  Strategy    : unless_stopped
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 3600s
  Multiplier  : x2
────────────────────────────────────
Job ID        : 4
Dataset       : -
Status        : RUNNING
Node          : controller
Kind          : composite
Created At    : 2026-11-02 17:39 UTC
Updated At    : 2026-11-02 17:39 UTC
Trigger       : one_shot
Retry Strategy
  Strategy    : unless_stopped
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 3600s
  Multiplier  : x2
────────────────────────────────────
Job ID        : 2
Dataset       : acme/eth_mainnet
Manifest Hash : b9e2ebd92c0752ba8a61a233f9cc5d3f4f8b601b1b789a882a5dd8ece9bca56b
Status        : ERROR
Node          : worker
End Block     : 24000199
Kind          : materialize-raw
Created At    : 2026-11-02 17:38 UTC
Updated At    : 2026-11-02 17:40 UTC
Trigger       : one_shot
Retry Strategy
  Strategy    : unless_stopped
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 3600s
  Multiplier  : x2
────────────────────────────────────
Job ID        : 1
Dataset       : -
Status        : RUNNING
Node          : controller
Kind          : composite
Created At    : 2026-11-02 17:38 UTC
Updated At    : 2026-11-02 17:40 UTC
Trigger       : one_shot
Retry Strategy
  Strategy    : unless_stopped
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 3600s
  Multiplier  : x2
────────────────────────────────────
```
:::

A deployment's `composite` job, the one `deploy` prints, shows `-` as its `Dataset`; the job that writes the tables
names it. `End Block` is `none` for a deployment with no end block. `Trigger` is `one_shot` for a job that runs until it
ends, and `interval(every_secs=3600)` for the `gc` job, which runs every hour. When nothing matches, it prints
`No active materializations found.`, whatever `--status` is.

The list is in pages of `--limit` jobs. To read the next page, pass the last job ID it printed to `--last-id`:

```bash
ampctl dataset list materialized --status all --limit 3 --last-id 4
```

With `--json`, the jobs are under `datasets`, each with the fields Amp stores for it, like `kind`, `status`,
`end_block`, its settings, and `composite_id`, the ID of its deployment:

:::terminal
```bash
ampctl dataset list materialized --status all --json | jq '.datasets[0] | {job_id, kind, status, dataset_namespace, dataset_name, end_block, composite_id}'
```

```json
{
  "job_id": 6,
  "kind": "gc",
  "status": "COMPLETED",
  "dataset_namespace": "acme",
  "dataset_name": "eth_transfers",
  "end_block": null,
  "composite_id": 4
}
```
:::

### `--status <STATUS>`

Which jobs `list materialized` and [`versions materialized`](/clis/ampctl/dataset#ampctl-dataset-versions-materialized) list, by status.

* **Type**: `active`; `all`; or one or more [job statuses](/managing-amp/jobs/lifecycle), separated by commas, in any
  case, like `scheduled,running` or `FATAL`
* **Default**: `active`: the jobs that haven't ended, so every status but `COMPLETED`, `STOPPED`, and `FATAL`

### Errors

* `INVALID_QUERY_PARAMETERS: invalid query parameters: Failed to deserialize query string: status: invalid status: bogus…`:
  a status in `--status` isn't one Amp has.
* `LIMIT_TOO_LARGE: limit 2000 exceeds maximum allowed limit of 1000`, or `LIMIT_INVALID: limit must be greater than 0`:
  `--limit` is out of range.

## `ampctl dataset inspect`

Shows a version's tags, kind, manifest hash, start block, and tables.

```
ampctl dataset inspect [OPTIONS] NAMESPACE/NAME@REVISION
```

| Argument                  | Type   | Default  | Description                                                                  |
| ------------------------- | ------ | -------- | ---------------------------------------------------------------------------- |
| `NAMESPACE/NAME@REVISION` | string | required | The version, like `acme/eth_transfers@1.0.0` or `acme/eth_transfers@latest`. |

Its alias is `ampctl dataset get`.

:::terminal
```bash
ampctl dataset inspect acme/eth_transfers@1.0.0
```

```
Namespace:             acme
Name:                  eth_transfers
Revision:              1.0.1, 1.0.0, latest, dev
Kind:                  manifest
Manifest Hash:         fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26
Start Block:           0
Finalized Blocks Only: false
Tables:                transfers
```
:::

`Revision` lists every tag that points to the manifest, so you can tell which version `latest` and `dev` are. It's the
revision you passed when no tag points to it, like a manifest hash. The other fields are those
[`register`](/clis/ampctl/dataset#ampctl-dataset-register) prints. With `--json`, `revision` is the revision you passed, and `tags` lists
the tags:

```json
{
  "namespace": "acme",
  "name": "eth_mainnet",
  "revision": "latest",
  "manifest_hash": "b9e2ebd92c0752ba8a61a233f9cc5d3f4f8b601b1b789a882a5dd8ece9bca56b",
  "kind": "evm-rpc",
  "start_block": 24000000,
  "finalized_blocks_only": false,
  "tables": ["blocks", "logs", "transactions"],
  "tags": ["1.0.0", "latest", "dev"]
}
```

A version that isn't registered fails with `✗ dataset not found: acme/eth_transfers@9.9.9`.

## `ampctl dataset versions`

Lists a dataset's version tags, with the manifest each points to, and its `latest` and `dev` tags.

```
ampctl dataset versions [OPTIONS] NAMESPACE/NAME
```

| Argument         | Type   | Default  | Description                             |
| ---------------- | ------ | -------- | --------------------------------------- |
| `NAMESPACE/NAME` | string | required | The dataset, like `acme/eth_transfers`. |

:::terminal
```bash
ampctl dataset versions acme/eth_transfers
```

```
Dataset: acme/eth_transfers

Latest version: 1.1.0
Dev hash: 4f0f4272544f8f3a7d960217cdba94e3fff57a15a4389337aefefb575b57a4fe

Versions:
  1.1.0 (4f0f4272544f8f3a7d960217cdba94e3fff57a15a4389337aefefb575b57a4fe)
    Created: 2026-11-02T17:40:36.464403+00:00
    Updated: 2026-11-02T17:40:36.464403+00:00
  1.0.1 (fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26)
    Created: 2026-11-02T17:39:19.781740+00:00
    Updated: 2026-11-02T17:39:19.781740+00:00
  1.0.0 (fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26)
    Created: 2026-11-02T17:39:04.645303+00:00
    Updated: 2026-11-02T17:39:04.645303+00:00
```
:::

Here, a second version of `eth_transfers.json`, with a `tx_index` column after `log_index`, was registered as `1.1.0`.
`Dev hash` is the manifest `dev` points to. A tag's `Updated` time changes when registering moves it to another
manifest. A dataset that doesn't exist isn't an error: it prints `No versions found`. With `--json`:

```json
{
  "namespace": "acme",
  "name": "eth_transfers",
  "versions": [
    {
      "version": "1.1.0",
      "manifest_hash": "4f0f4272544f8f3a7d960217cdba94e3fff57a15a4389337aefefb575b57a4fe",
      "created_at": "2026-11-02T17:40:36.464403+00:00",
      "updated_at": "2026-11-02T17:40:36.464403+00:00"
    },
    {
      "version": "1.0.1",
      "manifest_hash": "fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26",
      "created_at": "2026-11-02T17:39:19.781740+00:00",
      "updated_at": "2026-11-02T17:39:19.781740+00:00"
    },
    {
      "version": "1.0.0",
      "manifest_hash": "fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26",
      "created_at": "2026-11-02T17:39:04.645303+00:00",
      "updated_at": "2026-11-02T17:39:04.645303+00:00"
    }
  ],
  "special_tags": { "latest": "1.1.0", "dev": "4f0f4272544f8f3a7d960217cdba94e3fff57a15a4389337aefefb575b57a4fe" }
}
```

## `ampctl dataset versions materialized`

Lists the [jobs](/clis/ampctl/dataset#deployments) of one dataset's deployments, across its versions, newest first. It works like
[`list materialized`](/clis/ampctl/dataset#ampctl-dataset-list-materialized), for one dataset, and lists the jobs that write the tables and
the `gc` jobs, without the `composite` ones.

```
ampctl dataset versions materialized [OPTIONS] NAMESPACE/NAME
```

| Argument / flag           | Type              | Default  | Description                                                                             |
| ------------------------- | ----------------- | -------- | --------------------------------------------------------------------------------------- |
| `NAMESPACE/NAME`          | string            | required | The dataset, like `acme/eth_transfers`.                                                 |
| `-s`, `--status <STATUS>` | string            | `active` | Which jobs to list, by status, like `--status all`. See [`--status`](/clis/ampctl/dataset#--status-status). |
| `-l`, `--limit <LIMIT>`   | integer, 1 to 100 | `50`     | How many jobs to list, like `--limit 10`.                                               |
| `--last-id <LAST_ID>`     | integer           | none     | Lists the jobs older than this job ID, like `--last-id 5`, to read the next page.       |

The dataset comes after `materialized`: `ampctl dataset versions acme/eth_transfers materialized` fails.

:::terminal
```bash
ampctl dataset versions materialized acme/eth_transfers --status all --limit 2
```

```
Materialized Datasets
────────────────────────────────────
Job ID        : 6
Dataset       : acme/eth_transfers
Manifest Hash : fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26
Status        : COMPLETED
Node          : worker
Kind          : gc
Created At    : 2026-11-02 17:39 UTC
Updated At    : 2026-11-02 17:39 UTC
Trigger       : interval(every_secs=3600)
Retry Strategy
  Strategy    : unless_stopped
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 3600s
  Multiplier  : x2
────────────────────────────────────
Job ID        : 5
Dataset       : acme/eth_transfers
Manifest Hash : fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26
Status        : RUNNING
Node          : worker
End Block     : none
Kind          : materialize-derived
Created At    : 2026-11-02 17:39 UTC
Updated At    : 2026-11-02 17:39 UTC
Trigger       : one_shot
Retry Strategy
  Strategy    : unless_stopped
  Backoff     : exponential
  Base Delay  : 1s
  Max Delay   : 3600s
  Multiplier  : x2
────────────────────────────────────
Next Cursor: 5
```
:::

When a page is full, `Next Cursor` is the ID to pass to `--last-id` for the next one, and `next_cursor` holds it with
`--json`. A `--limit` above 100 fails with `error: invalid value '101' for '--limit <LIMIT>': 101 is not in 1..=100`.

## `ampctl dataset manifest`

Prints a version's manifest, as JSON, so you can read it, or save it to change it and register a new version.

```
ampctl dataset manifest [OPTIONS] NAMESPACE/NAME@REVISION
```

| Argument / flag           | Type   | Default  | Description                                                                            |
| ------------------------- | ------ | -------- | -------------------------------------------------------------------------------------- |
| `NAMESPACE/NAME@REVISION` | string | required | The version, like `acme/eth_transfers@1.0.0`.                                          |
| `-o`, `--output <OUTPUT>` | path   | none     | Writes the manifest to this file instead of printing it, like `-o eth_transfers.json`. |

:::terminal
```bash
ampctl dataset manifest acme/eth_mainnet@1.0.0
```

```
{
  "kind": "evm-rpc",
  "network": "mainnet",
  "start_block": 24000000,
  "finalized_blocks_only": false,
  "tables": {
    "blocks": {
      "schema": {
        "arrow": {
          "fields": [
            {
              "name": "_block_num",
              "type": "UInt64",
              "nullable": false
            },
…
```
:::

It prints the manifest Amp stores, indented. With `--json`, it prints it on one line. With `--output`, it writes what it
would print to the file, replacing any file there, and says so on stderr.

```bash
ampctl dataset manifest acme/eth_transfers@1.1.0 -o eth_transfers.json
```

### Errors

* `✗ manifest not found: acme/eth_transfers@9.9.9`: the dataset or the version isn't registered.
* `✗ failed to write manifest to '/nonexistent/dir/m.json'`, then `→ No such file or directory (os error 2)`: the file
  can't be written there. Check that its directory exists and that you can write to it.

## `ampctl dataset remove`

Removes a dataset, or one of its version tags.

```
ampctl dataset remove [OPTIONS] NAMESPACE/NAME[@VERSION]
```

| Argument / flag            | Type   | Default  | Description                                                                                          |
| -------------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------- |
| `NAMESPACE/NAME[@VERSION]` | string | required | The dataset, like `acme/eth_transfers`, or one of its version tags, like `acme/eth_transfers@1.0.0`. |
| `-f`, `--force`            | flag   | off      | Removes without asking first. Use it in scripts.                                                     |

Its alias is `ampctl dataset rm`.

**Removing a version tag** deletes the tag alone. Its manifest stays registered, so any other tag that points to it, a
reference by its hash, and its deployment keep working, and the tables keep their data. The tag `latest` points to can't
be removed, and `@latest`, `@dev`, and manifest hashes are rejected.

**Removing a dataset** deletes its registration: every version tag, and every manifest that no other dataset uses. Its
tables keep their files in object storage, and registering the same manifest again brings the dataset back, with its
data. A dataset with a deployment that hasn't ended can't be removed: [stop](/clis/ampctl/dataset#ampctl-dataset-stop) it first.

Amp doesn't check whether other datasets depend on the dataset you remove. Their tables keep their data, but deploying
them fails with `DEPENDENCY_NOT_FOUND` until it's registered again. [Lineage](/managing-amp/lineage) shows what depends
on a dataset.

Without `--force`, `remove` says what it deletes and asks first. Any answer but `y` or `yes` removes nothing, and exits
with code 0. So does a script without `--force`, since there's no answer to read.

```bash
ampctl dataset remove acme/eth_transfers@1.0.0
```

Removing a dataset or a version that doesn't exist succeeds too, so you can run it again safely. With `--json`, it
prints what it removed:

:::terminal
```bash
ampctl dataset remove acme/eth_transfers@1.0.0 --force --json
```

```json
{ "fqn": "acme/eth_transfers", "version": "1.0.0" }
```
:::

### Errors

* ``✗ cannot delete dataset with active jobs (stop them first with `ampctl dataset stop`): [DATASET_JOB_CONFLICT] Dataset revision 'acme/eth_transfers@fceb18fb7f3d2be31ea324a0d8760ff3e3440c212a7bea0a0b65016ff613af26' cannot be deleted while job '4' is in status 'RUNNING'``:
  a deployment of the dataset hasn't ended. Stop it with [`stop`](/clis/ampctl/dataset#ampctl-dataset-stop), using the manifest hash the
  message names if no tag points to it, then remove the dataset.
* `✗ cannot delete latest version: [CANNOT_DELETE_LATEST_VERSION] Cannot delete version tagged as 'latest' - create a newer version first`:
  the version is the dataset's highest. Register a higher one first, or remove the whole dataset.
* `error: invalid value 'acme/eth_transfers@latest' for '<REFERENCE>': cannot remove '@latest': only explicit version tags (e.g. @1.0.0) can be removed`:
  only version tags can be removed, not `latest`, `dev`, or a manifest hash.

## `ampctl dataset restore`

Rebuilds Amp's records of a version's tables from their files in [object storage](/running-amp/storage). Amp records
each Parquet file it writes in its [metadata database](/running-amp/metadata-database), and queries read those records
to find the files. When the records are lost but the files aren't, like when you restore the database from an old
backup, or start a new Amp on storage that another one wrote, `restore` reads the files back into the records, so
queries find the data again.

```
ampctl dataset restore [OPTIONS] NAMESPACE/NAME@REVISION
```

| Argument / flag           | Type    | Default    | Description                                                                                                              |
| ------------------------- | ------- | ---------- | ------------------------------------------------------------------------------------------------------------------------ |
| `NAMESPACE/NAME@REVISION` | string  | required   | The version, like `acme/eth_transfers@1.0.0`. It must be registered.                                                     |
| `--table <TABLE>`         | string  | all tables | Restores this table alone, like `--table blocks`.                                                                        |
| `--location-id <ID>`      | integer | none       | With `--table`, makes this [table revision](/managing-amp/table-revisions) the one queries read, like `--location-id 1`. |

Amp keeps a table's files in a directory, a *revision* of the table, which it gives a location ID. Each version of a
dataset writes its own revisions, and queries of a version read its active one. `restore` finds the newest revision of
each table in object storage, records its files, and makes it active.

Here, the metadata database was lost and the datasets registered again. Their tables have no records, so queries fail,
with `table 'acme/eth_mainnet.blocks' has no synced data`, until `restore` runs:

:::terminal
```bash
ampctl dataset restore acme/eth_mainnet@1.0.0
```

```
✓ Dataset restored successfully
→ Restored 3 table(s):
  • blocks (location_id: 1, url: file:///Users/you/amp-quickstart/.amp/data/acme/eth_mainnet/blocks/01a19d57-708b-79e3-9269-0a40fe18ac98/)
  • transactions (location_id: 2, url: file:///Users/you/amp-quickstart/.amp/data/acme/eth_mainnet/transactions/01a19d57-7098-70f1-923c-eb026174bf97/)
  • logs (location_id: 3, url: file:///Users/you/amp-quickstart/.amp/data/acme/eth_mainnet/logs/01a19d57-7092-72e1-aabe-c0f04e26d86b/)
```
:::

Then [deploying](/clis/ampctl/dataset#ampctl-dataset-deploy) the version carries on from the last block the files hold. With `--json`, each
table has its name, location ID, and URL:

```json
{
  "tables": [
    {
      "table_name": "transfers",
      "location_id": 4,
      "url": "file:///Users/you/amp-quickstart/.amp/data/acme/eth_transfers/transfers/01a19d57-e193-7472-ac67-1f31adca9887/"
    }
  ]
}
```

:::warning
`restore` finds a table's newest revision among those of every version of the dataset, not only the version you name.
When several versions have written a table, it can make another version's revision active, with that version's data.
Then name the revision with `--location-id`.
:::

`--location-id` makes one revision of a table active, by its location ID, which
[`ampctl table list`](/clis/ampctl/table) prints. Amp doesn't check that the revision belongs to the table you name, so
check the ID first:

```bash
ampctl dataset restore acme/eth_mainnet@1.0.0 --table blocks --location-id 1
```

With `--json`, it prints the table and the location ID: `{"table":"blocks","location_id":1}`. For files at a path other
than the one Amp would write, like data copied from another system, register the path as a revision and restore its
files with [`ampctl table`](/clis/ampctl/table) first, then make it active here with `--location-id`.

### Errors

* `TABLE_NOT_IN_MANIFEST: Table 'transfer' not found in dataset manifest`: the version has no table of that name. Check
  the names [`inspect`](/clis/ampctl/dataset#ampctl-dataset-inspect) prints.
* `REVISION_NOT_FOUND: No revision found for location_id 999`: no revision has that location ID.
* `unexpected response (status 404): {"error_code":"DATASET_NOT_FOUND",…}`, after `✗ restore failed`: the dataset or
  the version isn't registered. [Register](/clis/ampctl/dataset#ampctl-dataset-register) its manifest first.
* `error: the following required arguments were not provided: --table <TABLE>`: `--location-id` needs `--table`.
