diff --git a/edosl0util/crio.py b/edosl0util/crio.py
index 776978c15a125497bad05b2c7ab33874e9c8846f..fa0d98b364509b0138ff53bbd87aad29092fac8a 100644
--- a/edosl0util/crio.py
+++ b/edosl0util/crio.py
@@ -6,6 +6,10 @@ import numbers
 from edosl0util.headers import BaseStruct, DaySegmentedTimecode
 
 
+class ReadError(ValueError):
+    """Unable to parse construction record due to improper format"""
+
+
 def read(cr_file):
     """Parse a PDS construction record from a file (*00.PDS)"""
 
@@ -42,14 +46,17 @@ def read(cr_file):
                 rv['file_info'].append(d)
             extra = f.read()
             if extra:
-                raise ValueError('{} bytes remain after reading CR'.format(len(extra)))
+                raise ReadError('{} bytes remain after reading CR'.format(len(extra)))
             return rv
 
     def read_into_dict(f, struct, data):
         data.update(read_struct(f, struct))
 
     def read_struct(f, struct):
-        rv = struct_to_dict(struct.from_buffer_copy(f.read(c.sizeof(struct))))
+        buf = f.read(c.sizeof(struct))
+        if len(buf) < c.sizeof(struct):
+            raise ReadError('Unexpected EOF reading CR')
+        rv = struct_to_dict(struct.from_buffer_copy(buf))
         rv = {k: v for k, v in rv.items() if not k.startswith('spare_')}  # no spare fields
         return {k: int(v) if isinstance(v, numbers.Integral) else v for k, v in
                 rv.items()}  # no longs