diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,11 @@
 
 ## UNRELEASED
 
+## 3.1.1 - 2023-06-26
+
+* Added instances for `HasVariables` with custom error messages to avoid the issue of
+  missing `Generic` instances causing difficult to understand type errors.
+
 ## 3.1.0 - 2023-04-10
 
 * **BREAKING**: Change the type of `postcondition` to allow you to
diff --git a/quickcheck-dynamic.cabal b/quickcheck-dynamic.cabal
--- a/quickcheck-dynamic.cabal
+++ b/quickcheck-dynamic.cabal
@@ -1,6 +1,6 @@
 cabal-version:   2.2
 name:            quickcheck-dynamic
-version:         3.1.0
+version:         3.1.1
 license:         Apache-2.0
 license-files:
   LICENSE
@@ -32,6 +32,8 @@
   default-language:   Haskell2010
   default-extensions:
     ConstraintKinds
+    QuantifiedConstraints
+    DataKinds
     DeriveFunctor
     DeriveFoldable
     DeriveTraversable
@@ -77,7 +79,7 @@
         Test.QuickCheck.StateModel.Variables
     build-depends:
         QuickCheck -any,
-        base >=4.7 && <5,
+        base >= 4.7 && <5,
         random -any,
         mtl -any,
         containers -any,
diff --git a/src/Test/QuickCheck/StateModel/Variables.hs b/src/Test/QuickCheck/StateModel/Variables.hs
--- a/src/Test/QuickCheck/StateModel/Variables.hs
+++ b/src/Test/QuickCheck/StateModel/Variables.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE AllowAmbiguousTypes #-}
-{-# LANGUAGE QuantifiedConstraints #-}
 {-# LANGUAGE UndecidableInstances #-}
 
 module Test.QuickCheck.StateModel.Variables (
@@ -20,6 +19,7 @@
 ) where
 
 import Data.Data
+import Data.Kind
 import Data.List
 import Data.Map (Map)
 import Data.Map qualified as Map
@@ -27,6 +27,7 @@
 import Data.Set (Set)
 import Data.Set qualified as Set
 import GHC.Generics
+import GHC.TypeLits
 import GHC.Word
 import Test.QuickCheck as QC
 
@@ -44,8 +45,6 @@
 -- appear in a value.
 class HasVariables a where
   getAllVariables :: a -> Set (Any Var)
-  default getAllVariables :: (Generic a, GenericHasVariables (Rep a)) => a -> Set (Any Var)
-  getAllVariables = genericGetAllVariables . from
 
 instance HasVariables a => HasVariables (Smart a) where
   getAllVariables (Smart _ a) = getAllVariables a
@@ -132,7 +131,24 @@
 unsafeNextVarIndex :: VarContext -> Int
 unsafeNextVarIndex (VarCtx vs) = 1 + maximum (0 : [i | Some (Var i) <- Set.toList vs])
 
-instance {-# OVERLAPPABLE #-} (Generic a, GenericHasVariables (Rep a)) => HasVariables a
+-- NOTE: This trick is taken from this blog post:
+-- https://blog.csongor.co.uk/report-stuck-families/
+data Dummy x
+type family Break (c :: Constraint) (rep :: Type -> Type) :: Constraint where
+  Break _ Dummy = ((), ())
+  Break _ _ = ()
+
+instance
+  {-# OVERLAPPABLE #-}
+  ( Break
+      (TypeError ( 'Text "Missing instance of HasVariables for non-Generic type " ':<>: 'ShowType a))
+      (Rep a)
+  , Generic a
+  , GenericHasVariables (Rep a)
+  ) =>
+  HasVariables a
+  where
+  getAllVariables = genericGetAllVariables . from
 
 class GenericHasVariables f where
   genericGetAllVariables :: f k -> Set (Any Var)
