diff --git a/src/protocol/websocket.cpp b/src/protocol/websocket.cpp
index 514ff6db61c91df4ead6e9f81b37f20988b2c865..ed6ae71ca333a04eefc7043e3c7856ff06ce4fb7 100644
--- a/src/protocol/websocket.cpp
+++ b/src/protocol/websocket.cpp
@@ -42,6 +42,7 @@ using ftl::net::internal::Connection_TLS;
 struct wsheader_type {
     unsigned header_size;
     bool fin;
+    int rsv;
     bool mask;
     enum opcode_type {
         CONTINUATION = 0x0,
@@ -112,21 +113,21 @@ int ws_prepare(wsheader_type::opcode_type op, bool useMask, uint32_t mask,
 }
 
 // parse ws header, returns true on success
-// TODO(Seb): return error code for different results (not enough bytes in buffer
-//    to build the header vs corrputed/invalid header)
-bool ws_parse(uchar *data, size_t len, wsheader_type *ws) {
-    if (len < 2) return false;
+void ws_parse(uchar *data, size_t len, wsheader_type *ws) {
+    if (len < 2) throw FTL_Error("Websock header too small");
 
     ws->fin = (data[0] & 0x80) == 0x80;
+    ws->rsv = (data[0] & 0x70);
     ws->opcode = (wsheader_type::opcode_type) (data[0] & 0x0f);
     ws->mask = (data[1] & 0x80) == 0x80;
     ws->N0 = (data[1] & 0x7f);
     ws->header_size = 2 + (ws->N0 == 126? 2 : 0) + (ws->N0 == 127? 8 : 0) + (ws->mask? 4 : 0);
 
-    if (len < ws->header_size) return false;
+    if (len < ws->header_size) throw FTL_Error("Websock header too small");
+    if (ws->rsv != 0) throw FTL_Error("WS header reserved not zero");
 
     // invalid opcode, corrupted header?
-    if ((ws->opcode > 10) || ((ws->opcode > 2) && (ws->opcode < 8))) return false;
+    if ((ws->opcode > 10) || ((ws->opcode > 2) && (ws->opcode < 8))) throw FTL_Error("Websock opcode invalid");
 
     int i = 0;
     if (ws->N0 < 126) {
@@ -161,13 +162,11 @@ bool ws_parse(uchar *data, size_t len, wsheader_type *ws) {
         ws->masking_key[2] = 0;
         ws->masking_key[3] = 0;
     }
-
-    return true;
 }
 
 // same as above, pointer type casted to unsigned
-bool ws_parse(char *data, size_t len, wsheader_type *ws) {
-    return ws_parse(reinterpret_cast<unsigned char*>(data), len, ws);
+void ws_parse(char *data, size_t len, wsheader_type *ws) {
+    ws_parse(reinterpret_cast<unsigned char*>(data), len, ws);
 }
 
 
@@ -289,9 +288,7 @@ bool WebSocketBase<SocketT>::prepare_next(char* data, size_t data_len, size_t& o
     if (data_len < 14) { return false; }
 
     wsheader_type header;
-    if (!ws_parse(data, data_len, &header)) {
-        throw FTL_Error("corrupted WS header");
-    }
+    ws_parse(data, data_len, &header);
 
     if ((header.N + header.header_size) > data_len) {
         /*LOG(WARNING) << "buffered: " << data_len