diff --git a/src/error.rs b/src/error.rs
index c6f8e9b5e6fd247d708b39c3a34ba681e5b03b13..f9b35dbb2f6ce76638ccd50e15b2de6fd3e20ce2 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -86,6 +86,13 @@ pub enum Error {
     SerialPort(#[from] serialport::Error),
     #[error("I/O error: {0}")]
     IO(#[from] std::io::Error),
+    #[error("No data available to read from serial (or timeout too short)")]
+    NoDataAvailable,
+    #[error("Incomplete read: {amount_read} bytes read. {inner}")]
+    IncompleteRead {
+        amount_read: usize,
+        inner: Box<Self>,
+    },
     #[error("Channel error: {0}")]
     Channel(#[from] std::sync::mpsc::SendError<Vec<u8>>),
     #[error("Parse error")]
@@ -121,6 +128,8 @@ impl Error {
             Error::InvalidWriteData(_) => "serialbridge:invalid_input",
             Error::SerialPort(_) => "serialbridge:serial_error",
             Error::IO(_) => "serialbridge:serial_error",
+            Error::NoDataAvailable => "serialbridge:serial_error",
+            Error::IncompleteRead { .. } => "serialbridge:serial_error",
             Error::Channel(_) => "serialbridge:channel_error",
             Error::Parse => "serialbridge:parse_error",
             Error::Matlab(_) => "serialbridge:matlab_error",
diff --git a/src/lib.rs b/src/lib.rs
index 2e2dd29ac4c0d5eee99f4753034f5b9abbacb2d6..4ef314a031cc163ef7c193d75002815b9e84d20d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -146,15 +146,20 @@ fn read_from_serial(mut outputs: Output<'_>, args: Args<'_>) -> SResult<()> {
             Error::InvalidMatlabType("do not use decimal units, use a positive integer".into()),
         )));
     }
-    let n_doubles = arg as usize;
+    let n_singles = arg as usize;
 
     // Read n_doubles from the serial port
-    let bytes = SERIAL.read().read_n_bytes(&port, n_doubles * 4)?;
+    let n_bytes = n_singles * 4;
+    let bytes = SERIAL.read().read_n_bytes(&port, n_bytes)?;
     let doubles = bytes
         .chunks_exact(4)
         .map(|chunk| f32::from_be_bytes(chunk.try_into().unwrap()))
         .collect::<Vec<f32>>();
-    warn_debug!("Read {} bytes from serial port", n_doubles);
+    warn_debug!(
+        "Read {} ({} singles) bytes from serial port",
+        n_bytes,
+        n_singles
+    );
 
     outputs.set(doubles.to_vec())?;
     Ok(())
diff --git a/src/serial.rs b/src/serial.rs
index 731be06a7bab7ae620bec11d3498e4d7757d0001..95d08c250cc8b7ddd939c513a42960b475d17e04 100644
--- a/src/serial.rs
+++ b/src/serial.rs
@@ -59,7 +59,26 @@ impl SerialManager {
         let map = self.serial_map.read();
         let port = map.get(name).ok_or(Error::SerialNotOpen)?;
         let mut buf = vec![0; n];
-        port.lock().read_exact(&mut buf)?;
+        // implement a read exact to allow better error messages
+        let mut reader = port.lock();
+        let mut filled = 0;
+        while filled < n {
+            match reader.read(&mut buf[filled..]) {
+                Ok(n) => filled += n,
+                Err(e) => match e.kind() {
+                    std::io::ErrorKind::TimedOut => {
+                        if filled == 0 {
+                            return Err(Error::NoDataAvailable);
+                        }
+                        return Err(Error::IncompleteRead {
+                            amount_read: filled,
+                            inner: Box::new(Error::NoDataAvailable),
+                        });
+                    }
+                    _ => return Err(e.into()),
+                },
+            }
+        }
         Ok(buf)
     }
 
diff --git a/src/types.rs b/src/types.rs
index c2e78b2b3479d490edf5e0ccdbc17dc3ecb3d2dd..97fca4f661d40606d0e9bac8636660938060a5dc 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -16,7 +16,9 @@ pub trait IntoRustType<T> {
 impl IntoRustType<CString> for MxArray {
     fn into_rust(self) -> SResult<CString> {
         Ok(CharArray::from_mx_array(self)
-            .mexerr(Error::InvalidMatlabType("use a string instead".into()))?
+            .mexerr(Error::InvalidMatlabType(
+                "use a char array instead ('value')".into(),
+            ))?
             .get_cstring())
     }
 }
@@ -32,7 +34,7 @@ impl IntoRustType<f64> for MxArray {
     fn into_rust(self) -> SResult<f64> {
         let out = Numeric::<f64, _>::from_mx_array(self)
             .mexerr(Error::InvalidMatlabType(
-                "use a numerical type instead".into(),
+                "use a double numerical type instead".into(),
             ))?
             .data()
             .first()
@@ -58,7 +60,7 @@ impl IntoRustType<Vec<f32>> for MxArray {
     fn into_rust(self) -> SResult<Vec<f32>> {
         let out = Numeric::<f32, _>::from_mx_array(self)
             .mexerr(Error::InvalidMatlabType(
-                "use a numerical type instead".into(),
+                "use an array of singles (floats) type instead".into(),
             ))?
             .data()
             .to_owned();
@@ -70,7 +72,7 @@ impl IntoRustType<Vec<f64>> for MxArray {
     fn into_rust(self) -> SResult<Vec<f64>> {
         let out = Numeric::<f64, _>::from_mx_array(self)
             .mexerr(Error::InvalidMatlabType(
-                "use a numerical type instead".into(),
+                "use an array of doubles type instead".into(),
             ))?
             .data()
             .to_owned();