diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014, Omari Norman
+Copyright (c) 2014 - 2020 Omari Norman
 
 All rights reserved.
 
diff --git a/lib/Rainbox.hs b/lib/Rainbox.hs
--- a/lib/Rainbox.hs
+++ b/lib/Rainbox.hs
@@ -67,17 +67,20 @@
   , tableByColumns
 
   -- * Bi-color tables
+  --
+  -- | Build tables with rows of alternating background colors.
   , BicolorTableCellLine
   , BicolorTableCell
   , BicolorTableRow
   , BicolorTable(..)
-  , bicolorTable
+  , bicolorTableToBox
   , hPutBicolorTable
   , putBicolorTable
 
   -- ** van Laarhoven lenses
   , bctEvenBackground
   , bctOddBackground
+  , bctSpacerWidth
   , bctAlignments
   , bctRows
 
diff --git a/lib/Rainbox/BicolorTable.hs b/lib/Rainbox/BicolorTable.hs
--- a/lib/Rainbox/BicolorTable.hs
+++ b/lib/Rainbox/BicolorTable.hs
@@ -4,6 +4,7 @@
 module Rainbox.BicolorTable where
 
 import Control.Lens
+import Data.Foldable (foldl')
 import Data.Sequence (Seq)
 import qualified Data.Sequence as Seq
 import Rainbow
@@ -21,10 +22,10 @@
 -- | The set of all lines within a cell in a 'BicolorTable'.
 type BicolorTableCell = Seq BicolorTableCellLine
 
--- | The set of all columns in a single row.  The length of each
--- 'BicolorTableRow' must be equal to the length of
--- '_bctAlignments'; otherwise, 'bicolorTable' will fail with an
--- error message.
+-- | The set of all columns in a single row.  If any single row is
+-- narrower than the widest row in the table, it will be padded with
+-- empty cells so that it is the same width as the widest row in the
+-- table.
 type BicolorTableRow = Seq BicolorTableCell
 
 -- | Description for a table with rows of alternating background colors.  For
@@ -59,9 +60,9 @@
   -- ^ The width of each column of spacer cells.
 
   , _bctAlignments :: Seq (Alignment Vertical)
-  -- ^ Specifies the alignment for each column in the table.  The
-  -- length of this 'Seq' must be equal to '_bctColumnCount';
-  -- otherwise 'bicolorTable' will fail with an error message.
+  -- ^ Specifies the alignment for each column in the table.  If any
+  -- row in '_bctRows' is longer than this 'Seq', each extra column
+  -- is assumed to have an alignment 'left'.
 
   , _bctRows :: Seq BicolorTableRow
   -- ^ Specifies all the textual and color data for the
@@ -74,32 +75,20 @@
 
 makeLenses ''BicolorTable
 
--- | Creates a bi-color table.  If the number of columns in each
--- 'BicolorTableRow' is not equal to the length of '_bctAlignments',
--- this will return 'Left'; otherwise, returns 'Right' with a 'Box'
--- 'Vertical' that can then be rendered.
-bicolorTable :: BicolorTable -> Either String (Box Vertical)
-bicolorTable = fmap tableByRows . bicolorToPlainTable
+-- | Transforms a 'BicolorTable' to a 'Box'.
+bicolorTableToBox :: BicolorTable -> Box Vertical
+bicolorTableToBox = tableByRows . bicolorToPlainTable
 
 -- | Creates a bi-color table and renders it to the given 'Handle'
--- using 'bicolorTable' and 'hPutBox'.  Any errors from
--- 'bicolorTable' are repored with 'fail'.
+-- using 'bicolorTable' and 'hPutBox'.
 hPutBicolorTable :: Handle -> BicolorTable -> IO ()
-hPutBicolorTable h tbl = do
-  box <- either fail return . bicolorTable $ tbl
-  hPutBox h box
+hPutBicolorTable h = hPutBox h . bicolorTableToBox
 
 -- | Creates a bi-color table and renders it to standard output
 -- using 'hPutBicolorTable'.
 putBicolorTable :: BicolorTable -> IO ()
 putBicolorTable = hPutBicolorTable stdout
 
--- | Number each row of a 'Seq' with its row number.
-numberSeq :: Seq a -> Seq (Int, a)
-numberSeq ls = Seq.zip nums ls
-  where
-    nums = Seq.iterateN (Seq.length ls) succ 0
-
 -- | Convert a 'Chunk' for rendering by substituting the table's
 -- row background for the chunk's row background if applicable.
 convertChunkForRendering
@@ -160,26 +149,37 @@
   -> Seq (Alignment Vertical)
   -- ^ Column alignments
   -> BicolorTableRow
-  -> Either String (Seq Cell)
-bicolorToPlainRow bkgdEven bkgdOdd sepWidth colNum aligns columns
-  | Seq.length columns /= Seq.length aligns = Left $ "length of row number " ++ show colNum
-      ++ ": " ++ show (Seq.length columns)
-      ++ " (should be: " ++ show (Seq.length aligns) ++ ")"
-  | otherwise = Right row'
+  -> Seq Cell
+bicolorToPlainRow bkgdEven bkgdOdd sepWidth colNum aligns
+  = Seq.intersperse spcr
+  . Seq.zipWith (bicolorToPlainCell bkgd) aligns
   where
-    row' = Seq.intersperse spcr
-      $ Seq.zipWith (bicolorToPlainCell bkgd) aligns columns
-      where
-        bkgd | even colNum = bkgdEven
-             | otherwise = bkgdOdd
-        spcr = separator bkgd sepWidth
+    bkgd | even colNum = bkgdEven
+         | otherwise = bkgdOdd
+    spcr = separator bkgd sepWidth
 
 -- | Converts a BicolorTable table to a plain table with 'Cell'.  Does all
 -- necessary Chunk conversions, and includes spacer cells.
 bicolorToPlainTable
   :: BicolorTable
-  -> Either String (Seq (Seq Cell))
-bicolorToPlainTable (BicolorTable bkgdEven bkgdOdd sepWidth aligns rws)
-  = Seq.traverseWithIndex f rws
+  -> Seq (Seq Cell)
+bicolorToPlainTable bct = Seq.mapWithIndex f rws
   where
+    (BicolorTable bkgdEven bkgdOdd sepWidth aligns rws) = padBicolorTable bct
     f rowIdx = bicolorToPlainRow bkgdEven bkgdOdd sepWidth rowIdx aligns
+
+-- | Pads out '_bctAlignments' so that it is as long as the longest
+-- row in the table, and pads out each row in '_bctRows' so that it
+-- is as long as the longest row in the table.
+padBicolorTable :: BicolorTable -> BicolorTable
+padBicolorTable bct
+  = bct & over bctRows padRows
+        & over bctAlignments padAligns
+  where
+    maxLen = foldl' max 0 . fmap Seq.length . _bctRows $ bct
+    padRows = fmap pad
+      where
+        pad row = row <>
+          Seq.replicate (max 0 (maxLen - Seq.length row)) Seq.empty
+    padAligns aligns = aligns
+      <> Seq.replicate (max 0 (maxLen - Seq.length aligns)) left
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -4,10 +4,10 @@
 name: rainbox
 synopsis: Two-dimensional box pretty printing, with colors
 description: Please see README.md
-version: 0.24.4.0
+version: 0.26.0.0
 license: BSD3
 license-file: LICENSE
-copyright: Copyright 2014-2019 Omari Norman
+copyright: Copyright 2014-2020 Omari Norman
 author: Omari Norman
 maintainer: omari@smileystation.com
 stability: Experimental
diff --git a/rainbox.cabal b/rainbox.cabal
--- a/rainbox.cabal
+++ b/rainbox.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.31.1.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 07e54d4d70b9548a75f55b7873816d300d314c2e403c2e8fb9229f2b029d47c4
+-- hash: 193ccd0b7369b9e4c418620fcc9b26fc75f29e88edb4dad7b788f1a44827f352
 
 name:           rainbox
-version:        0.24.4.0
+version:        0.26.0.0
 synopsis:       Two-dimensional box pretty printing, with colors
 description:    Please see README.md
 category:       System
@@ -16,7 +16,7 @@
 bug-reports:    https://www.github.com/massysett/rainbox/issues
 author:         Omari Norman
 maintainer:     omari@smileystation.com
-copyright:      Copyright 2014-2019 Omari Norman
+copyright:      Copyright 2014-2020 Omari Norman
 license:        BSD3
 license-file:   LICENSE
 build-type:     Simple
diff --git a/test/Rainbox/Instances.hs b/test/Rainbox/Instances.hs
--- a/test/Rainbox/Instances.hs
+++ b/test/Rainbox/Instances.hs
@@ -4,6 +4,7 @@
 import Control.Monad
 import Test.QuickCheck
 import Rainbox.Core
+import Rainbox.BicolorTable
 import Rainbow.Instances ()
 import Data.Sequence (Seq)
 import qualified Data.Sequence as Seq
@@ -59,3 +60,6 @@
 
 instance Arbitrary Cell where
   arbitrary = liftM4 Cell arbitrary arbitrary arbitrary arbitrary
+
+instance Arbitrary BicolorTable where
+  arbitrary = BicolorTable <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
diff --git a/test/rainbox-properties.hs b/test/rainbox-properties.hs
--- a/test/rainbox-properties.hs
+++ b/test/rainbox-properties.hs
@@ -1,6 +1,7 @@
 module Main where
 
 import Rainbox.Core
+import Rainbox.BicolorTable
 import Rainbox.Instances ()
 import Rainbow.Types
 import Test.Tasty
@@ -102,6 +103,22 @@
           wdth = width mrge
       in counterexample (show (mrge, wdth, lenR)) $ wdth == lenR
     ]
+
+    , testGroup "BicolorTable"
+      [ testGroup "padBicolorTable"
+        [ testProperty "all rows are the same length" $ \bct ->
+          let padded = padBicolorTable bct
+          in case Seq.viewl . _bctRows $ padded of
+              EmptyL -> True
+              a :< as -> all (\sq -> Seq.length sq == Seq.length a) as
+
+        , testProperty "length of _bctAlignment is at least as long as a row" $ \bct ->
+          let padded = padBicolorTable bct
+          in case Seq.viewl . _bctRows $ padded of
+              EmptyL -> True
+              a :< _ -> Seq.length (_bctAlignments padded) >= Seq.length a
+        ]
+      ]
 
 
   ]
