---
title: "Validator Upgrade Guide"
description: "Validator Upgrade Guide explains GenLayer validator breaking and non-breaking upgrades, database handling, and downtime expectations."
source: https://docs.genlayer.com/validators/upgrade
last_updated: 2026-10-20
---

# Validator Upgrade Guide

A GenLayer validator upgrade is either **non-breaking** or **breaking**, and the upgrade type determines whether the database carries over and how much downtime to expect. Before upgrading, check the [changelog](/validators/changelog) for the target version to confirm the correct procedure.

| Upgrade Type | How to Identify | Database | Downtime |
|---|---|---|---|
| **Non-breaking** | Patch/minor release, no consensus contract changes | Carries over | Minimal |
| **Breaking** | Changelog mentions "upgrade consensus contracts" or new consensus deployment | Must be deleted | Full restart required |

> **Note:**
> When in doubt, treat it as a breaking change — the only cost is a longer sync time.

---

## Non-Breaking Upgrade

No re-staking is required. You can minimize downtime by preparing the new version while your current node is still running.

1. **Download and extract into a fresh folder** — See [download instructions](/validators/setup-guide#download-the-node-software). Always use a clean directory.
2. **Configure the new version** — Set up `config.yaml` and `.env` as described in the [configuration section](/validators/setup-guide#configuration). You can reference your previous settings, but **do not blindly copy config files** — new versions may include updated defaults or new fields.
3. **Copy the data folder** — Copy `data/` from your old installation to the new one (contains database and keystore). Skip this if your `datadir` points outside the project directory.
4. **Validate** — Run `./bin/genlayernode doctor` and ensure all checks pass.
5. **Switch over** — Stop the old node, then start the new one.

---

## Breaking Change Upgrade

Breaking changes involve a new consensus deployment. The old database is incompatible, so it cannot be reused. **Re-staking is required** — you must stake again using the [validator wizard](/validators/setup-guide#using-the-validator-wizard).

> **Warning:**
> **Always back up your keystore before a breaking upgrade.** You can copy the `data/node/keystore/` directory or use `genlayernode account export`. See [backing up your operator key](/validators/setup-guide#backing-up-your-operator-key).

1. **Read the changelog** — Check the [changelog](/validators/changelog) for version-specific instructions and what changed.
2. **Back up your keystore** — Copy `data/node/keystore/` to a safe location.
3. **Download and extract into a fresh folder** — See [download instructions](/validators/setup-guide#download-the-node-software).
4. **Configure from scratch** — Create `config.yaml` and `.env` using the new example files as a base. **Do not copy your old config** — the schema may have changed. Refer to the [configuration section](/validators/setup-guide#configuration) for the current format.
5. **Import your operator key** — Copy your backed-up keystore into `data/node/keystore/`, or re-import using the CLI. See [restoring your operator key](/validators/setup-guide#restoring-your-operator-key).
6. **Do NOT copy the old database** — If you copied the full `data/` folder, delete everything in `data/node/` except `keystore/`: the stores `genvm.db` and `ops.db`, the Merkle state in `merkle/`, and the pre-v0.6 `genlayer.db` if present. If you set custom `merkleforest` or `merkletree` paths, delete those too. The node creates fresh stores and syncs from genesis.
7. **Validate** — Run `./bin/genlayernode doctor` and ensure all checks pass.
8. **Stop the old node, start the new one.**

---

## Migration Notes

### v0.5.x to v0.6.0 (Breaking)

- Bradbury Phase 2 is a new deployment on a new chain, with a new `consensusaddress` and a new staking contract. Phase 1 validators are not carried over: join again as a validator, with stake, on Phase 2. Follow the [breaking upgrade](#breaking-change-upgrade) steps.
- The node needs the trusted protocol manifest of the network. Set `consensus.manifestpath` (default `configs/node/protocol-manifest.json`) and `consensus.chainid`. The release package has no network files: take the manifest and values from [Network-Specific Consensus Configuration](/validators/setup-guide#network-specific-consensus-configuration).
- GenVM moved from `third_party/genvm` to `opt/genvm/<version>` (v0.6.0-rc.1: `opt/genvm/v0.6.0-rc10`). Set `genvm.root_dir: ./opt/genvm/v0.6.0-rc10` and run `python3 ./opt/genvm/v0.6.0-rc10/bin/setup.py` (see [download instructions](/validators/setup-guide#download-the-node-software)).
- The Bradbury RPC WebSocket needs an API key. Set it in the environment as `GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCKEY`; it has no `config.yaml` key. See [Testnet Bradbury](/validators/setup-guide#testnet-bradbury).
- The `genlayer_debug` (`gen_dbg_*`) and `zksync` (`zks_*`) RPC groups are off in the default `config.yaml` (`node.rpc.endpoints`).
- The data store is split into `genvm.db` and `ops.db`. On startup the node renames an old `genlayer.db` to `genvm.db`; it refuses to start if both exist.
- Docker: `NODE_PASSWORD` has no default, and in v0.6.0-rc.1 every `docker compose` command fails while it is empty. It reaches the node as `GENLAYERNODE_PASSWORD`, not as `--password`. See [Running the Node using docker-compose](/validators/setup-guide#running-the-node-using-docker-compose).
- Docker: the v0.6.0-rc.1 compose file does not mount the protocol manifest. Mount it in a `docker-compose.override.yml` (see [Running the Node using docker-compose](/validators/setup-guide#running-the-node-using-docker-compose)).
- Docker: the node container runs as uid `10001`. Make `./data` writable by it once: `sudo chown -R 10001:10001 ./data`.
- Docker: the node no longer mounts `/var/run/docker.sock`. It reaches Docker through the read-only `docker-socket-proxy` service.
- Docker: if you mount your own GenVM config files (for example a customized LLM config for greyboxing, in a `docker-compose.override.yml`), move every mount from `/app/third_party/genvm/config/<file>` to `/app/opt/genvm/v0.6.0-rc10/config/<file>` (v0.6.0-rc.1). v0.6 no longer reads the old path, so a mount left there is ignored without an error and the image's default config loads.
- Docker: the v0.6.0-rc.1 compose file has no fixed project name. Set `COMPOSE_PROJECT_NAME=genlayer-node` in `.env` (or pass `-p genlayer-node`), so `docker compose up` from a new version's directory replaces the containers of the previous version instead of failing with "container name ... already in use".
- Monitoring: the `CENTRAL_*` URLs and credentials have no defaults. Alloy stops at startup if any is unset. See [Monitoring](/validators/monitoring).
- Do not use `genlayernode run --upgrade` in v0.6: the call that resumes the node is not available yet, so the node waits forever.

### v0.4.x to v0.5.0 (Breaking)

- The two consensus contract addresses (`contractmainaddress` and `contractdataaddress`) have been replaced by a single `consensusaddress` field. Do not copy your old consensus config — use the new example `config.yaml`.
- The GenLayer Chain ZKSync RPC URLs (`genlayerchainrpcurl` and `genlayerchainwebsocketurl`) have changed. Update both the HTTP RPC and WebSocket URLs in your `config.yaml` to the new endpoints.
- Database must be wiped (the node creates a fresh one on startup).
- Re-staking is required — breaking changes involve a new consensus deployment, so you must stake again using the [validator wizard](/validators/setup-guide#using-the-validator-wizard).

---

## Quick Troubleshooting

- **Node won't start** — Run `./bin/genlayernode doctor`. If it reports unknown config fields, reconfigure from the new example.
- **Not participating in consensus** — Verify the consensus contract address, `validatorWalletAddress`, and `operatorAddress` are correct.
- **Key errors** — Your operator key wasn't imported. See [restoring your operator key](/validators/setup-guide#restoring-your-operator-key).
- **Slow sync after breaking upgrade** — Expected. Ensure `genesis` is set in `config.yaml` to avoid scanning from block 0.
