diff --git a/api/etherbone.h b/api/etherbone.h
index bafc718cdb648beff958f579539ee6cf9058d1a4..e85c0a5987e6eb902b521a6e4c625669bf7c07f0 100644
--- a/api/etherbone.h
+++ b/api/etherbone.h
@@ -280,17 +280,19 @@ EB_PUBLIC
 void eb_device_flush(eb_device_t device);
 
 /* Begin a wishbone cycle on the remote device.
- * Read/write phases within a cycle hold the device locked.
+ * Read/write operations within a cycle hold the device locked.
  * Read/write operations are executed in the order they are queued.
  * Until the cycle is closed and flushed, the operations are not sent.
- * If there is insufficient memory, EB_NULL is returned.
+ * If there is insufficient memory to begin a cycle, EB_NULL is returned.
  * 
  * Your callback is called from either eb_socket_poll or eb_device_flush.
  * It receives these arguments: (user_data, operations, status)
  * 
  * If status != OK, the cycle was never sent to the remote bus.
  * If status == OK, the cycle was sent.
- * Individual wishbone operation error status is reported by 'operations'.
+ *
+ * When status == EB_OK, 'operations' report the wishbone ERR flag.
+ * When status != EB_OK, 'operations' points to the offending operation.
  *
  * Status codes:
  *   OK		- operation completed successfully
@@ -298,7 +300,7 @@ void eb_device_flush(eb_device_t device);
  *   WIDTH      - a specified value exceeded device bus port width
  *   OVERFLOW	- too many operations queued for this cycle (wire limit)
  *   TIMEOUT    - remote system never responded to EB request
- *   FAIL       - underlying transport has broken connection
+ *   FAIL       - remote host violated protocol
  *   OOM        - out of memory while queueing operations to the cycle
  */
 EB_PUBLIC
diff --git a/api/format/master.c b/api/format/master.c
index 0680a59b2d00e4cde97429bf1b7eb7bf9ec009d5..e8bdb306e07a18706ba920ea9cfe675eccf36f30 100644
--- a/api/format/master.c
+++ b/api/format/master.c
@@ -62,22 +62,31 @@ void eb_device_flush(eb_device_t devicep) {
   struct eb_response* response;
   eb_cycle_t cyclep, nextp, prevp;
   eb_response_t responsep;
-  eb_width_t biggest, data;
+  eb_width_t biggest, data, width;
+  eb_data_t data_mask;
+  eb_address_t address_mask;
   uint8_t buffer[sizeof(eb_max_align_t)*(255+255+1+1)+8]; /* big enough for worst-case record */
   uint8_t * wptr, * cptr, * eob;
   int alignment, record_alignment, header_alignment, stride, mtu, readback;
   
   device = EB_DEVICE(devicep);
   transport = EB_TRANSPORT(device->transport);
+  width = device->widths;
   
   /*
   assert (device->passive != devicep);
-  assert (eb_width_refined(device->widths) != 0);
+  assert (eb_width_refined(width) != 0);
   */
   
+  /* Determine alignment and masking sets */
+  data_mask = ((eb_data_t)1) << (((width&EB_DATAX)<<3)-1);
+  data_mask = (data_mask-1) << 1 | 1;
+  address_mask = ((eb_address_t)1) << (((width&EB_ADDRX)>>1)-1);
+  address_mask = (address_mask-1) << 1 | 1;
+  
   /* Calculate alignment values */
-  data = device->widths & EB_DATAX;
-  biggest = (device->widths >> 4) | data;
+  data = width & EB_DATAX;
+  biggest = (width >> 4) | data;
   alignment = 2;
   alignment += (biggest >= EB_DATA32)*2;
   alignment += (biggest >= EB_DATA64)*4;
@@ -93,7 +102,7 @@ void eb_device_flush(eb_device_t devicep) {
     buffer[0] = 0x4E;
     buffer[1] = 0x6F;
     buffer[2] = 0x10; /* V1. no probe. */
-    buffer[3] = device->widths;
+    buffer[3] = width;
     cptr = wptr = &buffer[header_alignment];
     eob = &buffer[mtu];
   } else {
@@ -117,6 +126,7 @@ void eb_device_flush(eb_device_t devicep) {
     eb_operation_t scanp;
     int needs_check, cycle_end;
     unsigned int ops, maxops;
+    eb_status_t reason;
     
     cycle = EB_CYCLE(cyclep);
     nextp = cycle->next;
@@ -137,6 +147,38 @@ void eb_device_flush(eb_device_t devicep) {
       continue;
     }
     
+    /* Are there out of range widths? */
+    reason = EB_OK; /* silence warning */
+    for (operationp = cycle->first; operationp != EB_NULL; operationp = operation->next) {
+      operation = EB_OPERATION(operationp);
+      /* Is the address too big for a bus op? */
+      if ((operation->flags & EB_OP_CFG_SPACE) == 0 &&
+          (operation->address & address_mask) != operation->address) {
+        reason = EB_ADDRESS;
+        break;
+      }
+      /* Is the address too big for a cfg op? */
+      if ((operation->flags & EB_OP_CFG_SPACE) != 0 &&
+          (operation->address & 0xFFFFU) != operation->address) {
+        reason = EB_ADDRESS;
+        break;
+      }
+      /* Is the data too big for the port? */
+      if ((operation->flags & EB_OP_MASK) == EB_OP_WRITE &&
+          (operation->write_value & data_mask) != operation->write_value) {
+        reason = EB_WIDTH;
+        break;
+      }
+    }
+    if (operationp != EB_NULL) {
+      /* Report the bad operation to the user */
+      if (cycle->callback)
+        (*cycle->callback)(cycle->user_data, operationp, reason);
+      eb_cycle_destroy(cyclep);
+      eb_free_cycle(cyclep);
+      continue;
+    }
+    
     /* Record to hook it into socket */
     responsep = eb_new_response(); /* invalidates: cycle device transport */
     if (responsep == EB_NULL) {
@@ -310,7 +352,7 @@ void eb_device_flush(eb_device_t devicep) {
           if (length > eob - wptr) {
             /* Blow up in the face of the user */
             if (cycle->callback)
-              (*cycle->callback)(cycle->user_data, cycle->first, EB_OVERFLOW);
+              (*cycle->callback)(cycle->user_data, operationp, EB_OVERFLOW);
             eb_cycle_destroy(cyclep);
             eb_free_cycle(cyclep);
             eb_free_response(responsep);
diff --git a/api/glue/socket.c b/api/glue/socket.c
index 646afb1d11f993cb5a96d4fc601fb177d109c262..56642ef8a0d61b80cf332dc2edcb894eaa81daf5 100644
--- a/api/glue/socket.c
+++ b/api/glue/socket.c
@@ -184,7 +184,7 @@ eb_status_t eb_socket_close(eb_socket_t socketp) {
     /* Report the cycle callback */
     cycle = EB_CYCLE(response->cycle);
     if (cycle->callback)
-      (*cycle->callback)(cycle->user_data, cycle->first, EB_FAIL); /* invalidate: socket response cycle */
+      (*cycle->callback)(cycle->user_data, cycle->first, EB_TIMEOUT); /* invalidate: socket response cycle */
     
     socket = EB_SOCKET(socketp);
     response = EB_RESPONSE(tmp);