diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go
index b9a3fe2442258bb623c6d7cfd6b73379c99ddfbb..d2fb6934b9c29814ca5a3727f96eba88d77558c1 100644
--- a/consensus/clique/clique.go
+++ b/consensus/clique/clique.go
@@ -503,13 +503,24 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro
 	header.Nonce = types.BlockNonce{}
 
 	number := header.Number.Uint64()
+
+	// Assemble the voting snapshot to check which votes make sense
+	snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
+	if err != nil {
+		return err
+	}
 	if number%c.config.Epoch != 0 {
 		c.lock.RLock()
-		if len(c.proposals) > 0 {
-			addresses := make([]common.Address, 0, len(c.proposals))
-			for address := range c.proposals {
+
+		// Gather all the proposals that make sense voting on
+		addresses := make([]common.Address, 0, len(c.proposals))
+		for address, authorize := range c.proposals {
+			if snap.validVote(address, authorize) {
 				addresses = append(addresses, address)
 			}
+		}
+		// If there's pending proposals, cast a vote on them
+		if len(addresses) > 0 {
 			header.Coinbase = addresses[rand.Intn(len(addresses))]
 			if c.proposals[header.Coinbase] {
 				copy(header.Nonce[:], nonceAuthVote)
@@ -519,11 +530,7 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro
 		}
 		c.lock.RUnlock()
 	}
-	// Assemble the voting snapshot and set the correct difficulty
-	snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
-	if err != nil {
-		return err
-	}
+	// Set the correct difficulty
 	header.Difficulty = diffNoTurn
 	if snap.inturn(header.Number.Uint64(), c.signer) {
 		header.Difficulty = diffInTurn
diff --git a/consensus/clique/snapshot.go b/consensus/clique/snapshot.go
index 8eaf3b62e4f34ffb57a29023962659cb0446c15d..32a1191dbe63972e1be152e8b8e866f887c64aad 100644
--- a/consensus/clique/snapshot.go
+++ b/consensus/clique/snapshot.go
@@ -126,11 +126,17 @@ func (s *Snapshot) copy() *Snapshot {
 	return cpy
 }
 
+// validVote returns whether it makes sense to cast the specified vote in the
+// given snapshot context (e.g. don't try to add an already authorized signer).
+func (s *Snapshot) validVote(address common.Address, authorize bool) bool {
+	_, signer := s.Signers[address]
+	return (signer && !authorize) || (!signer && authorize)
+}
+
 // cast adds a new vote into the tally.
 func (s *Snapshot) cast(address common.Address, authorize bool) bool {
 	// Ensure the vote is meaningful
-	_, signer := s.Signers[address]
-	if (signer && authorize) || (!signer && !authorize) {
+	if !s.validVote(address, authorize) {
 		return false
 	}
 	// Cast the vote into an existing or new tally