ethereum/go-ethereum · critical

clique (poa) sealing not supported any more

Error message

clique (poa) sealing not supported any more

What it means

Clique's Seal implementation unconditionally panics with 'clique (poa) sealing not supported any more'. In this codebase, the Clique engine is retained for verifying/reading PoA chains while block production (sealing new blocks through consensus.Engine.Seal) has been removed, so any attempt to mint a Clique block crashes by design.

Source

Thrown at consensus/clique/clique.go:593

// Finalize implements consensus.Engine. There is no post-transaction
// consensus rules in clique, do nothing here.
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, blockAccessIndex uint32, bal *bal.ConstructionBlockAccessList) {
	// No block rewards in PoA, so the state remains as is
}

// Authorize injects a private key into the consensus engine to mint new blocks
// with.
func (c *Clique) Authorize(signer common.Address) {
	c.lock.Lock()
	defer c.lock.Unlock()

	c.signer = signer
}

// Seal implements consensus.Engine, attempting to create a sealed block using
// the local signing credentials.
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
	panic("clique (poa) sealing not supported any more")
}

// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
// that a new block should have:
// * DIFF_NOTURN(2) if BLOCK_NUMBER % SIGNER_COUNT != SIGNER_INDEX
// * DIFF_INTURN(1) if BLOCK_NUMBER % SIGNER_COUNT == SIGNER_INDEX
func (c *Clique) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
	snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil)
	if err != nil {
		return nil
	}
	c.lock.RLock()
	signer := c.signer
	c.lock.RUnlock()
	return calcDifficulty(snap, signer)
}

func calcDifficulty(snap *Snapshot, signer common.Address) *big.Int {

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Do not attempt to seal with this engine; use it only to validate existing clique chains.
  2. For a new private/consortium chain, use a consensus engine whose Seal is supported (e.g. a supported PoA/Aura-style engine in your fork) or an external signer design.
  3. Remove --mine or validator sealing config targeting clique.
  4. Pin to an older go-ethereum version if clique sealing is a hard requirement, while tracking the security tradeoff.

Example fix

// before
engine.Seal(chain, block, results, stop) // *clique.Clique -> panics

// after
// Use clique only for verification; produce blocks with a supported sealing engine.
Defensive patterns

Strategy: validation

Validate before calling

// guard before any sealing call
func canSeal(engine consensus.Engine) bool {
	_, ok := engine.(interface{ SealSupported() })
	return ok // clique.Clique does not advertise sealing in this build
}

Type guard

func isClique(e consensus.Engine) bool {
	_, ok := e.(*clique.Clique)
	return ok
}

Prevention

When it happens

Trigger: Running a node configured to seal with clique (e.g. a miner/validator setup calling engine.Seal, --mine with clique without a supported sealer, or custom code invoking Seal on a *clique.Clique instance). Any path reaching clique.Seal panics.

Common situations: Old private-PoA setups or tutorials that used clique for block production upgraded to a version where sealing was removed; tools/tests that call Seal directly on the consensus engine.

Related errors


AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15). Data as JSON: /api/errors/cab8f715d2c78775. Report an issue: GitHub.