diff --git a/Cargo.toml b/Cargo.toml
index f7696c3e19..32657b2d32 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -256,3 +256,6 @@ required-features = ["full"]
 name = "server"
 path = "tests/server.rs"
 required-features = ["full"]
+
+[patch.crates-io]
+http = { git = "https://github.com/glebpom/http", branch = "failable-headers-allocations" }
diff --git a/examples/upgrades.rs b/examples/upgrades.rs
index 38cfded386..6d8ef8d166 100644
--- a/examples/upgrades.rs
+++ b/examples/upgrades.rs
@@ -66,7 +66,8 @@ async fn server_upgrade(mut req: Request<Body>) -> Result<Response<Body>> {
     // made-up 'foobar' protocol.
     *res.status_mut() = StatusCode::SWITCHING_PROTOCOLS;
     res.headers_mut()
-        .insert(UPGRADE, HeaderValue::from_static("foobar"));
+        .try_insert(UPGRADE, HeaderValue::from_static("foobar"))
+        .expect("FIXME");
     Ok(res)
 }
 
diff --git a/src/client/client.rs b/src/client/client.rs
index bf4db79fde..2292e17378 100644
--- a/src/client/client.rs
+++ b/src/client/client.rs
@@ -257,7 +257,8 @@ where
 
             if self.config.set_host {
                 let uri = req.uri().clone();
-                req.headers_mut().entry(HOST).or_insert_with(|| {
+                let entry = headers_op!(req.headers_mut().try_entry(HOST), error);
+                headers_op!(entry.or_try_insert_with(|| {
                     let hostname = uri.host().expect("authority implies host");
                     if let Some(port) = get_non_default_port(&uri) {
                         let s = format!("{}:{}", hostname, port);
@@ -266,7 +267,7 @@ where
                         HeaderValue::from_str(hostname)
                     }
                     .expect("uri host is valid header value")
-                });
+                }), capacity);
             }
 
             // CONNECT always sends authority-form, so check it first...
@@ -752,6 +753,12 @@ enum ClientError<B> {
     },
 }
 
+impl<B> From<crate::error::Parse> for ClientError<B> {
+    fn from(e: crate::error::Parse) -> Self {
+        ClientError::Normal(e.into())
+    }
+}
+
 impl<B> ClientError<B> {
     fn map_with_reused(conn_reused: bool) -> impl Fn((crate::Error, Option<Request<B>>)) -> Self {
         move |(err, orig_req)| {
diff --git a/src/error.rs b/src/error.rs
index 5beedeb8b2..adea7fed98 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -65,6 +65,9 @@ pub(super) enum Kind {
     /// A general error from h2.
     #[cfg(feature = "http2")]
     Http2,
+
+    /// Error with HTTP request or response
+    Http(http::Error),
 }
 
 #[derive(Debug)]
@@ -518,6 +521,7 @@ impl Error {
             Kind::User(User::DispatchGone) => "dispatch task is gone",
             #[cfg(feature = "ffi")]
             Kind::User(User::AbortedByCallback) => "operation aborted by an application callback",
+            Kind::Http(ref _e) => "FIXME: HTTP request or response building error"
         }
     }
 }
@@ -559,6 +563,20 @@ impl From<Parse> for Error {
     }
 }
 
+#[doc(hidden)]
+impl From<http::CapacityOverflow> for Error {
+    fn from(err: http::CapacityOverflow) -> Error {
+        Error::new(Kind::Http(err.into()))
+    }
+}
+
+#[doc(hidden)]
+impl From<http::Error> for Error {
+    fn from(err: http::Error) -> Error {
+        Error::new(Kind::Http(err))
+    }
+}
+
 #[cfg(feature = "http1")]
 impl Parse {
     pub(crate) fn content_length_invalid() -> Self {
@@ -628,6 +646,34 @@ impl fmt::Display for TimedOut {
 
 impl StdError for TimedOut {}
 
+macro_rules! headers_op {
+    ($op:expr, capacity) => {
+        match $op {
+            Err(http::CapacityOverflow { .. }) =>  {
+                return Err(crate::error::Parse::TooLarge.into());
+            },
+            Ok(r) => r,
+        }
+    };
+    ($op:expr, error) => {
+        match $op {
+            Err(e) if e.is::<http::CapacityOverflow>() =>  {
+                return Err(crate::error::Parse::TooLarge.into());
+            },
+            Err(e) if e.is::<http::header::InvalidHeaderName>() =>  {
+                // FIXME!
+                return Err(crate::error::Parse::Internal.into());
+            },
+            Err(_e) =>  {
+                // FIXME!
+                return Err(crate::error::Parse::Internal.into());
+            },
+            Ok(r) => r,
+        }
+    };
+}
+
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/ext.rs b/src/ext.rs
index 224206dd66..8c6ea4d59e 100644
--- a/src/ext.rs
+++ b/src/ext.rs
@@ -5,7 +5,7 @@ use bytes::Bytes;
 use http::header::HeaderName;
 #[cfg(feature = "http1")]
 use http::header::{IntoHeaderName, ValueIter};
-use http::HeaderMap;
+use http::{CapacityOverflow, HeaderMap};
 #[cfg(feature = "ffi")]
 use std::collections::HashMap;
 #[cfg(feature = "http2")]
@@ -119,15 +119,17 @@ impl HeaderCaseMap {
     }
 
     #[cfg(any(test, feature = "ffi"))]
-    pub(crate) fn insert(&mut self, name: HeaderName, orig: Bytes) {
-        self.0.insert(name, orig);
+    pub(crate) fn try_insert(&mut self, name: HeaderName, orig: Bytes) -> Result<(), CapacityOverflow> {
+        self.0.try_insert(name, orig)?;
+        Ok(())
     }
 
-    pub(crate) fn append<N>(&mut self, name: N, orig: Bytes)
+    pub(crate) fn try_append<N>(&mut self, name: N, orig: Bytes) -> Result<(), CapacityOverflow>
     where
         N: IntoHeaderName,
     {
-        self.0.append(name, orig);
+        self.0.try_append(name, orig)?;
+        Ok(())
     }
 }
 
diff --git a/src/ffi/error.rs b/src/ffi/error.rs
index 015e595aee..b3017b7114 100644
--- a/src/ffi/error.rs
+++ b/src/ffi/error.rs
@@ -24,6 +24,8 @@ pub enum hyper_code {
     HYPERE_FEATURE_NOT_ENABLED,
     /// The peer sent an HTTP message that could not be parsed.
     HYPERE_INVALID_PEER_MESSAGE,
+    /// HTTP headers reached the maximum capacity
+    HYPERE_HEADERS_CAPACITY,
 }
 
 // ===== impl hyper_error =====
diff --git a/src/ffi/http_types.rs b/src/ffi/http_types.rs
index ea10f139cb..d0a62cdf09 100644
--- a/src/ffi/http_types.rs
+++ b/src/ffi/http_types.rs
@@ -468,8 +468,18 @@ ffi_fn! {
         let headers = non_null!(&mut *headers ?= hyper_code::HYPERE_INVALID_ARG);
         match unsafe { raw_name_value(name, name_len, value, value_len) } {
             Ok((name, value, orig_name)) => {
-                headers.headers.insert(&name, value);
-                headers.orig_casing.insert(name.clone(), orig_name.clone());
+                match headers.headers.try_insert(&name, value) {
+                    Err(http::CapacityOverflow { .. }) => {
+                        return hyper_code::HYPERE_HEADERS_CAPACITY;
+                    }
+                    Ok(_) => {},
+                }
+                match headers.orig_casing.try_insert(name.clone(), orig_name.clone()) {
+                    Err(http::CapacityOverflow { .. }) => {
+                        return hyper_code::HYPERE_HEADERS_CAPACITY;
+                    }
+                    Ok(()) => {},
+                }
                 headers.orig_order.insert(name);
                 hyper_code::HYPERE_OK
             }
@@ -488,8 +498,18 @@ ffi_fn! {
 
         match unsafe { raw_name_value(name, name_len, value, value_len) } {
             Ok((name, value, orig_name)) => {
-                headers.headers.append(&name, value);
-                headers.orig_casing.append(&name, orig_name.clone());
+                match headers.headers.try_append(&name, value) {
+                    Err(http::CapacityOverflow { .. }) => {
+                        return hyper_code::HYPERE_HEADERS_CAPACITY;
+                    }
+                    Ok(_) => {},
+                }
+                match headers.orig_casing.try_append(&name, orig_name.clone()) {
+                    Err(http::CapacityOverflow { .. }) => {
+                        return hyper_code::HYPERE_HEADERS_CAPACITY;
+                    }
+                    Ok(()) => {},
+                }
                 headers.orig_order.append(name);
                 hyper_code::HYPERE_OK
             }
diff --git a/src/headers.rs b/src/headers.rs
index 8407be185f..2839f0e037 100644
--- a/src/headers.rs
+++ b/src/headers.rs
@@ -2,7 +2,7 @@
 use bytes::BytesMut;
 use http::header::CONTENT_LENGTH;
 use http::header::{HeaderValue, ValueIter};
-use http::HeaderMap;
+use http::{CapacityOverflow, HeaderMap};
 #[cfg(all(feature = "http2", feature = "client"))]
 use http::Method;
 
@@ -100,10 +100,18 @@ pub(super) fn method_has_defined_payload_semantics(method: &Method) -> bool {
 }
 
 #[cfg(feature = "http2")]
-pub(super) fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) {
-    headers
-        .entry(CONTENT_LENGTH)
-        .or_insert_with(|| HeaderValue::from(len));
+pub(super) fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) -> Result<(), CapacityOverflow> {
+    match headers
+        .try_entry(CONTENT_LENGTH){
+        Err(e) if e.is::<CapacityOverflow>() => return Err(CapacityOverflow::new()),
+        Err(_) => {
+            unreachable!()
+        },
+        Ok(e) => {
+            e.or_try_insert_with(|| HeaderValue::from(len))?;
+        }
+    };
+    Ok(())
 }
 
 #[cfg(feature = "http1")]
diff --git a/src/lib.rs b/src/lib.rs
index e5e4cfc56e..9c7c0df4cf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -77,6 +77,7 @@ mod cfg;
 #[macro_use]
 mod common;
 pub mod body;
+#[macro_use]
 mod error;
 pub mod ext;
 #[cfg(test)]
diff --git a/src/proto/h1/conn.rs b/src/proto/h1/conn.rs
index 5ebff2803e..fe5824a827 100644
--- a/src/proto/h1/conn.rs
+++ b/src/proto/h1/conn.rs
@@ -551,7 +551,11 @@ where
             self.state.busy();
         }
 
-        self.enforce_version(&mut head);
+        if let Err(err) = self.enforce_version(&mut head) {
+            self.state.error = Some(err.into());
+            self.state.writing = Writing::Closed;
+            return None;
+        }
 
         let buf = self.io.headers_buf();
         match super::role::encode_headers::<T>(
@@ -587,7 +591,7 @@ where
     }
 
     // Fix keep-alive when Connection: keep-alive header is not present
-    fn fix_keep_alive(&mut self, head: &mut MessageHead<T::Outgoing>) {
+    fn fix_keep_alive(&mut self, head: &mut MessageHead<T::Outgoing>) -> Result<(), http::Error> {
         let outgoing_is_keep_alive = head
             .headers
             .get(CONNECTION)
@@ -604,20 +608,22 @@ where
                 Version::HTTP_11 => {
                     if self.state.wants_keep_alive() {
                         head.headers
-                            .insert(CONNECTION, HeaderValue::from_static("keep-alive"));
+                            .try_insert(CONNECTION, HeaderValue::from_static("keep-alive"))?;
                     }
                 }
                 _ => (),
             }
         }
+
+        Ok(())
     }
 
     // If we know the remote speaks an older version, we try to fix up any messages
     // to work with our older peer.
-    fn enforce_version(&mut self, head: &mut MessageHead<T::Outgoing>) {
+    fn enforce_version(&mut self, head: &mut MessageHead<T::Outgoing>) -> Result<(), http::Error> {
         if let Version::HTTP_10 = self.state.version {
             // Fixes response or connection when keep-alive header is not present
-            self.fix_keep_alive(head);
+            self.fix_keep_alive(head)?;
             // If the remote only knows HTTP/1.0, we should force ourselves
             // to do only speak HTTP/1.0 as well.
             head.version = Version::HTTP_10;
@@ -625,6 +631,8 @@ where
         // If the remote speaks HTTP/1.1, then it *should* be fine with
         // both HTTP/1.0 and HTTP/1.1 from us. So again, we just let
         // the user's headers be.
+
+        Ok(())
     }
 
     pub(crate) fn write_body(&mut self, chunk: B) {
@@ -1061,7 +1069,7 @@ mod tests {
         let io = tokio_test::io::Builder::new().build();
         let mut conn = Conn::<_, bytes::Bytes, crate::proto::h1::ServerTransaction>::new(io);
         *conn.io.read_buf_mut() = ::bytes::BytesMut::from(&s[..]);
-        conn.state.cached_headers = Some(HeaderMap::with_capacity(2));
+        conn.state.cached_headers = Some(HeaderMap::try_with_capacity(2).unwrap());
 
         let rt = tokio::runtime::Builder::new_current_thread()
             .enable_all()
diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs
index 6252207baf..0a2936938e 100644
--- a/src/proto/h1/role.rs
+++ b/src/proto/h1/role.rs
@@ -224,7 +224,7 @@ impl Http1Transaction for Server {
 
         let mut headers = ctx.cached_headers.take().unwrap_or_else(HeaderMap::new);
 
-        headers.reserve(headers_len);
+        headers_op!(headers.try_reserve(headers_len), capacity);
 
         for header in &headers_indices[..headers_len] {
             // SAFETY: array is valid up to `headers_len`
@@ -295,7 +295,7 @@ impl Http1Transaction for Server {
             }
 
             if let Some(ref mut header_case_map) = header_case_map {
-                header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
+                headers_op!(header_case_map.try_append(&name, slice.slice(header.name.0..header.name.1)), capacity);
             }
 
             #[cfg(feature = "ffi")]
@@ -303,7 +303,7 @@ impl Http1Transaction for Server {
                 header_order.append(&name);
             }
 
-            headers.append(name, value);
+            headers_op!(headers.try_append(name, value), capacity);
         }
 
         if is_te && !is_te_chunked {
@@ -1020,7 +1020,7 @@ impl Http1Transaction for Client {
                 None
             };
 
-            headers.reserve(headers_len);
+            headers_op!(headers.try_reserve(headers_len), capacity);
             for header in &headers_indices[..headers_len] {
                 // SAFETY: array is valid up to `headers_len`
                 let header = unsafe { &*header.as_ptr() };
@@ -1039,7 +1039,7 @@ impl Http1Transaction for Client {
                 }
 
                 if let Some(ref mut header_case_map) = header_case_map {
-                    header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
+                    headers_op!(header_case_map.try_append(&name, slice.slice(header.name.0..header.name.1)), capacity);
                 }
 
                 #[cfg(feature = "ffi")]
@@ -1047,7 +1047,12 @@ impl Http1Transaction for Client {
                     header_order.append(&name);
                 }
 
-                headers.append(name, value);
+                match headers.try_append(name.clone(), value) {
+                    Err(http::CapacityOverflow { .. }) =>  {
+                        return Err(Parse::TooLarge);
+                    },
+                    Ok(_) => {}
+                }
             }
 
             let mut extensions = http::Extensions::default();
@@ -1152,7 +1157,7 @@ impl Http1Transaction for Client {
         extend(dst, b"\r\n");
         msg.head.headers.clear(); //TODO: remove when switching to drain()
 
-        Ok(body)
+        body
     }
 
     fn on_error(_err: &crate::Error) -> Option<MessageHead<Self::Outgoing>> {
@@ -1233,12 +1238,12 @@ impl Client {
             Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
         }
     }
-    fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
+    fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> crate::Result<Encoder> {
         let body = if let Some(body) = body {
             body
         } else {
             head.headers.remove(header::TRANSFER_ENCODING);
-            return Encoder::length(0);
+            return Ok(Encoder::length(0));
         };
 
         // HTTP/1.0 doesn't know about chunked
@@ -1262,19 +1267,19 @@ impl Client {
             }
 
             return if let Some(len) = existing_con_len {
-                Encoder::length(len)
+                Ok(Encoder::length(len))
             } else if let BodyLength::Known(len) = body {
-                set_content_length(headers, len)
+                Ok(headers_op!(set_content_length(headers, len), error))
             } else {
                 // HTTP/1.0 client requests without a content-length
                 // cannot have any body at all.
-                Encoder::length(0)
+                Ok(Encoder::length(0))
             };
         }
 
         // If the user set a transfer-encoding, respect that. Let's just
         // make sure `chunked` is the final encoding.
-        let encoder = match headers.entry(header::TRANSFER_ENCODING) {
+        let encoder = match headers_op!(headers.try_entry(header::TRANSFER_ENCODING), error) {
             Entry::Occupied(te) => {
                 should_remove_con_len = true;
                 if headers::is_chunked(te.iter()) {
@@ -1314,7 +1319,7 @@ impl Client {
                     match head.subject.0 {
                         Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)),
                         _ => {
-                            te.insert(HeaderValue::from_static("chunked"));
+                            headers_op!(te.try_insert(HeaderValue::from_static("chunked")), capacity);
                             Some(Encoder::chunked())
                         }
                     }
@@ -1330,7 +1335,7 @@ impl Client {
             if should_remove_con_len && existing_con_len.is_some() {
                 headers.remove(header::CONTENT_LENGTH);
             }
-            return encoder;
+            return Ok(encoder);
         }
 
         // User didn't set transfer-encoding, AND we know body length,
@@ -1342,11 +1347,11 @@ impl Client {
             unreachable!("BodyLength::Unknown would set chunked");
         };
 
-        set_content_length(headers, len)
+        Ok(headers_op!(set_content_length(headers, len), error))
     }
 }
 
-fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
+fn set_content_length(headers: &mut HeaderMap, len: u64) -> Result<Encoder, http::Error> {
     // At this point, there should not be a valid Content-Length
     // header. However, since we'll be indexing in anyways, we can
     // warn the user if there was an existing illegal header.
@@ -1355,7 +1360,7 @@ fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
     // so perhaps only do that while the user is developing/testing.
 
     if cfg!(debug_assertions) {
-        match headers.entry(header::CONTENT_LENGTH) {
+        match headers.try_entry(header::CONTENT_LENGTH)? {
             Entry::Occupied(mut cl) => {
                 // Internal sanity check, we should have already determined
                 // that the header was illegal before calling this function.
@@ -1366,16 +1371,16 @@ fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
                 error!("user provided content-length header was invalid");
 
                 cl.insert(HeaderValue::from(len));
-                Encoder::length(len)
+                Ok(Encoder::length(len))
             }
             Entry::Vacant(cl) => {
-                cl.insert(HeaderValue::from(len));
-                Encoder::length(len)
+                cl.try_insert(HeaderValue::from(len))?;
+                Ok(Encoder::length(len))
             }
         }
     } else {
-        headers.insert(header::CONTENT_LENGTH, HeaderValue::from(len));
-        Encoder::length(len)
+        headers.try_insert(header::CONTENT_LENGTH, HeaderValue::from(len))?;
+        Ok(Encoder::length(len))
     }
 }
 
@@ -2391,10 +2396,10 @@ mod tests {
 
         let mut head = MessageHead::default();
         head.headers
-            .insert("content-length", HeaderValue::from_static("10"));
+            .try_insert("content-length", HeaderValue::from_static("10")).unwrap();
         head.headers
-            .insert("content-type", HeaderValue::from_static("application/json"));
-        head.headers.insert("*-*", HeaderValue::from_static("o_o"));
+            .try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
+        head.headers.try_insert("*-*", HeaderValue::from_static("o_o")).unwrap();
 
         let mut vec = Vec::new();
         Client::encode(
@@ -2419,12 +2424,12 @@ mod tests {
 
         let mut head = MessageHead::default();
         head.headers
-            .insert("content-length", HeaderValue::from_static("10"));
+            .try_insert("content-length", HeaderValue::from_static("10")).unwrap();
         head.headers
-            .insert("content-type", HeaderValue::from_static("application/json"));
+            .try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
 
         let mut orig_headers = HeaderCaseMap::default();
-        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
+        orig_headers.try_insert(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap();
         head.extensions.insert(orig_headers);
 
         let mut vec = Vec::new();
@@ -2453,12 +2458,12 @@ mod tests {
 
         let mut head = MessageHead::default();
         head.headers
-            .insert("content-length", HeaderValue::from_static("10"));
+            .try_insert("content-length", HeaderValue::from_static("10")).unwrap();
         head.headers
-            .insert("content-type", HeaderValue::from_static("application/json"));
+            .try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
 
         let mut orig_headers = HeaderCaseMap::default();
-        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
+        orig_headers.try_insert(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap();
         head.extensions.insert(orig_headers);
 
         let mut vec = Vec::new();
@@ -2508,11 +2513,11 @@ mod tests {
 
         let mut head = MessageHead::default();
         head.headers
-            .insert("content-length", HeaderValue::from_static("10"));
+            .try_insert("content-length", HeaderValue::from_static("10")).unwrap();
         head.headers
-            .insert("content-type", HeaderValue::from_static("application/json"));
+            .try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
         head.headers
-            .insert("weird--header", HeaderValue::from_static(""));
+            .try_insert("weird--header", HeaderValue::from_static("")).unwrap();
 
         let mut vec = Vec::new();
         Server::encode(
@@ -2540,12 +2545,12 @@ mod tests {
 
         let mut head = MessageHead::default();
         head.headers
-            .insert("content-length", HeaderValue::from_static("10"));
+            .try_insert("content-length", HeaderValue::from_static("10")).unwrap();
         head.headers
-            .insert("content-type", HeaderValue::from_static("application/json"));
+            .try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
 
         let mut orig_headers = HeaderCaseMap::default();
-        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
+        orig_headers.try_insert(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap();
         head.extensions.insert(orig_headers);
 
         let mut vec = Vec::new();
@@ -2574,12 +2579,12 @@ mod tests {
 
         let mut head = MessageHead::default();
         head.headers
-            .insert("content-length", HeaderValue::from_static("10"));
+            .try_insert("content-length", HeaderValue::from_static("10")).unwrap();
         head.headers
-            .insert("content-type", HeaderValue::from_static("application/json"));
+            .try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
 
         let mut orig_headers = HeaderCaseMap::default();
-        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
+        orig_headers.try_insert(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap();
         head.extensions.insert(orig_headers);
 
         let mut vec = Vec::new();
@@ -2636,9 +2641,9 @@ mod tests {
     fn test_write_headers_orig_case_empty_value() {
         let mut headers = HeaderMap::new();
         let name = http::header::HeaderName::from_static("x-empty");
-        headers.insert(&name, "".parse().expect("parse empty"));
+        headers.try_insert(&name, "".parse().expect("parse empty")).unwrap();
         let mut orig_cases = HeaderCaseMap::default();
-        orig_cases.insert(name, Bytes::from_static(b"X-EmptY"));
+        orig_cases.try_insert(name, Bytes::from_static(b"X-EmptY")).unwrap();
 
         let mut dst = Vec::new();
         super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
@@ -2653,12 +2658,12 @@ mod tests {
     fn test_write_headers_orig_case_multiple_entries() {
         let mut headers = HeaderMap::new();
         let name = http::header::HeaderName::from_static("x-empty");
-        headers.insert(&name, "a".parse().unwrap());
-        headers.append(&name, "b".parse().unwrap());
+        headers.try_insert(&name, "a".parse().unwrap()).unwrap();
+        headers.try_append(&name, "b".parse().unwrap()).unwrap();
 
         let mut orig_cases = HeaderCaseMap::default();
-        orig_cases.insert(name.clone(), Bytes::from_static(b"X-Empty"));
-        orig_cases.append(name, Bytes::from_static(b"X-EMPTY"));
+        orig_cases.try_insert(name.clone(), Bytes::from_static(b"X-Empty")).unwrap();
+        orig_cases.try_append(name, Bytes::from_static(b"X-EMPTY")).unwrap();
 
         let mut dst = Vec::new();
         super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
@@ -2793,8 +2798,8 @@ mod tests {
 
         let mut head = MessageHead::default();
         let mut headers = HeaderMap::new();
-        headers.insert("content-length", HeaderValue::from_static("10"));
-        headers.insert("content-type", HeaderValue::from_static("application/json"));
+        headers.try_insert("content-length", HeaderValue::from_static("10")).unwrap();
+        headers.try_insert("content-type", HeaderValue::from_static("application/json")).unwrap();
 
         b.iter(|| {
             let mut vec = Vec::new();
diff --git a/src/proto/h2/client.rs b/src/proto/h2/client.rs
index bac8eceb3a..56310eb215 100644
--- a/src/proto/h2/client.rs
+++ b/src/proto/h2/client.rs
@@ -371,7 +371,7 @@ where
                     super::strip_connection_headers(req.headers_mut(), true);
                     if let Some(len) = body.size_hint().exact() {
                         if len != 0 || headers::method_has_defined_payload_semantics(req.method()) {
-                            headers::set_content_length_if_missing(req.headers_mut(), len);
+                            headers::set_content_length_if_missing(req.headers_mut(), len)?;
                         }
                     }
 
diff --git a/src/proto/h2/server.rs b/src/proto/h2/server.rs
index 4127387e71..adfdb56b8d 100644
--- a/src/proto/h2/server.rs
+++ b/src/proto/h2/server.rs
@@ -482,8 +482,8 @@ where
 
                     // set Date header if it isn't already set...
                     res.headers_mut()
-                        .entry(::http::header::DATE)
-                        .or_insert_with(date::update_and_header_value);
+                        .try_entry(::http::header::DATE)?
+                        .or_try_insert_with(date::update_and_header_value)?;
 
                     if let Some(connect_parts) = connect_parts.take() {
                         if res.status().is_success() {
@@ -511,7 +511,7 @@ where
                     if !body.is_end_stream() {
                         // automatically set Content-Length from body...
                         if let Some(len) = body.size_hint().exact() {
-                            headers::set_content_length_if_missing(res.headers_mut(), len);
+                            headers::set_content_length_if_missing(res.headers_mut(), len)?;
                         }
 
                         let body_tx = reply!(me, res, false);
diff --git a/tests/server.rs b/tests/server.rs
index 786bb4b42f..c23d375de0 100644
--- a/tests/server.rs
+++ b/tests/server.rs
@@ -3003,7 +3003,7 @@ impl TestService {
                     *res.version_mut() = v;
                 }
                 Reply::Header(name, value) => {
-                    res.headers_mut().insert(name, value);
+                    res.headers_mut().try_insert(name, value)?;
                 }
                 Reply::Body(body) => {
                     *res.body_mut() = body;
diff --git a/tests/support/mod.rs b/tests/support/mod.rs
index 6b3c8f4472..5ae314de29 100644
--- a/tests/support/mod.rs
+++ b/tests/support/mod.rs
@@ -202,7 +202,7 @@ macro_rules! __internal_req_res_prop {
 macro_rules! __internal_headers_map {
     ($headers:ident, { $($name:expr => $val:expr,)* }) => {
         $(
-        $headers.insert($name, $val.to_string().parse().expect("header value"));
+        $headers.try_insert($name, $val.to_string().parse().expect("header value")).unwrap();
         )*
     }
 }