diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,13 @@
 # Changelog
 
+- 0.2.0 (2026-01-10)
+  * In order to better-match the spec, 'gen' now returns an
+    'Either Error BS.ByteString'. The new 'Error' value is returned
+    either in the exceptionally rare case that the DRBG needs a reseed
+    (previously this was just "error <msg>"), or, more likely to occur
+    in practice, if more than 65536 bytes are requested from the DRBG at
+    a time.
+
 - 0.1.3 (2025-12-28)
   * Adds an 'llvm' build flag and tests with GHC 9.10.3.
 
diff --git a/bench/Main.hs b/bench/Main.hs
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -22,14 +22,14 @@
     bgroup "HMAC-SHA256" [
       bench "new" $ whnfAppIO (DRBG.new SHA256.hmac mempty mempty) mempty
     , bench "reseed" $ whnfAppIO (DRBG.reseed mempty mempty) drbg256
-    , bench "gen (32B)"  $ nfAppIO (DRBG.gen mempty 32) drbg256
-    , bench "gen (256B)" $ nfAppIO (DRBG.gen mempty 256) drbg256
+    , bench "gen (32B)"  $ whnfAppIO (DRBG.gen mempty 32) drbg256
+    , bench "gen (256B)" $ whnfAppIO (DRBG.gen mempty 256) drbg256
     ]
   , bgroup "HMAC-SHA512" [
       bench "new" $ whnfAppIO (DRBG.new SHA512.hmac mempty mempty) mempty
     , bench "reseed" $ whnfAppIO (DRBG.reseed mempty mempty) drbg512
-    , bench "gen (32B)"  $ nfAppIO (DRBG.gen mempty 32) drbg512
-    , bench "gen (256B)" $ nfAppIO (DRBG.gen mempty 256) drbg512
+    , bench "gen (32B)"  $ whnfAppIO (DRBG.gen mempty 32) drbg512
+    , bench "gen (256B)" $ whnfAppIO (DRBG.gen mempty 256) drbg512
     ]
   ]
 
diff --git a/lib/Crypto/DRBG/HMAC.hs b/lib/Crypto/DRBG/HMAC.hs
--- a/lib/Crypto/DRBG/HMAC.hs
+++ b/lib/Crypto/DRBG/HMAC.hs
@@ -14,9 +14,10 @@
 module Crypto.DRBG.HMAC (
   -- * DRBG and HMAC function types
     DRBG
+  , HMAC
+  , Error(..)
   , _read_v
   , _read_k
-  , HMAC
 
   -- * DRBG interaction
   , new
@@ -53,6 +54,12 @@
 
 -- types ----------------------------------------------------------------------
 
+-- | A DRBG error.
+data Error =
+    MaxBytesExceeded -- ^ More than 65536 bytes have been requested.
+  | ReseedRequired   -- ^ The DRBG must be reseeded (via 'reseed').
+  deriving (Eq, Show)
+
 -- see SP 800-90A table 2
 _RESEED_COUNTER :: Word64
 _RESEED_COUNTER = (2 :: Word64) ^ (48 :: Word64)
@@ -143,10 +150,14 @@
 -- | Generate bytes from a DRBG, optionally injecting additional bytes
 --   per SP 800-90A.
 --
+--   Per SP 800-90A, the maximum number of bytes that can be requested
+--   on any invocation is 65536. Larger requests will return
+--   'MaxBytesExceeded'.
+--
 --   >>> import qualified Data.ByteString.Base16 as B16
 --   >>> drbg <- new SHA256.hmac entropy nonce personalization_string
---   >>> bytes0 <- gen addl_bytes 16 drbg
---   >>> bytes1 <- gen addl_bytes 16 drbg
+--   >>> Right bytes0 <- gen addl_bytes 16 drbg
+--   >>> Right bytes1 <- gen addl_bytes 16 drbg
 --   >>> B16.encode bytes0
 --   "938d6ca6d0b797f7b3c653349d6e3135"
 --   >>> B16.encode bytes1
@@ -156,12 +167,14 @@
   => BS.ByteString       -- ^ additional bytes to inject
   -> Word64              -- ^ number of bytes to generate
   -> DRBG (PrimState m)
-  -> m BS.ByteString
+  -> m (Either Error BS.ByteString)
 gen addl bytes (DRBG mut) = do
   drbg0 <- P.readMutVar mut
-  let !(Pair bs drbg1) = gen_pure addl bytes drbg0
-  P.writeMutVar mut drbg1
-  pure bs
+  case gen_pure addl bytes drbg0 of
+    Left e -> pure (Left e)
+    Right !(Pair bs drbg1) -> do
+      P.writeMutVar mut drbg1
+      pure (Right bs)
 
 -- | Reseed a DRBG.
 --
@@ -237,14 +250,15 @@
   :: BS.ByteString
   -> Word64
   -> DRBGState
-  -> Pair BS.ByteString DRBGState
+  -> Either Error (Pair BS.ByteString DRBGState)
 gen_pure addl bytes drbg0@(DRBGState h@(HMACEnv hmac outlen) _ _ _)
-    | r > _RESEED_COUNTER = error "ppad-hmac-drbg: reseed required"
+    | bytes > 0x10000     = Left MaxBytesExceeded
+    | r > _RESEED_COUNTER = Left ReseedRequired
     | otherwise =
         let !(Pair temp drbg1) = loop mempty 0 v1
             returned_bits = BS.take (fi bytes) temp
             drbg = update_pure addl drbg1
-        in  Pair returned_bits drbg
+        in  Right (Pair returned_bits drbg)
   where
     !(DRBGState _ r v1 k1)
       | BS.null addl = drbg0
diff --git a/ppad-hmac-drbg.cabal b/ppad-hmac-drbg.cabal
--- a/ppad-hmac-drbg.cabal
+++ b/ppad-hmac-drbg.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ppad-hmac-drbg
-version:            0.1.3
+version:            0.2.0
 synopsis:           HMAC-based deterministic random bit generator
 license:            MIT
 license-file:       LICENSE
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -103,7 +103,7 @@
   assertEqual "k0" k0 caseK0
 
   DRBG.reseed caseEntropy1 caseAddl1 drbg
-  _ <- DRBG.gen mempty bytes drbg
+  Right _ <- DRBG.gen mempty bytes drbg
   v1 <- DRBG._read_v drbg
   k1 <- DRBG._read_k drbg
 
@@ -111,7 +111,7 @@
   assertEqual "k1" k1 caseK1
 
   DRBG.reseed caseEntropy2 caseAddl2 drbg
-  returned <- DRBG.gen mempty bytes drbg
+  Right returned <- DRBG.gen mempty bytes drbg
   v2 <- DRBG._read_v drbg
   k2 <- DRBG._read_k drbg
 
