diff --git a/examples/client.cc b/examples/client.cc
index f8833ea5b8174109406a0c462e7b1431368f318a..c34aec00d98dc27dfdffdf5b73a48cc640b951ee 100644
--- a/examples/client.cc
+++ b/examples/client.cc
@@ -634,7 +634,7 @@ int recv_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
 } // namespace
 
 namespace {
-int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint16_t app_error_code,
+int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint64_t app_error_code,
                  void *user_data, void *stream_user_data) {
   auto c = static_cast<Client *>(user_data);
 
@@ -648,7 +648,7 @@ int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint16_t app_error_code,
 
 namespace {
 int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
-                 uint16_t app_error_code, void *user_data,
+                 uint64_t app_error_code, void *user_data,
                  void *stream_user_data) {
   auto c = static_cast<Client *>(user_data);
 
@@ -1969,7 +1969,7 @@ void Client::remove_tx_crypto_data(ngtcp2_crypto_level crypto_level,
   ::remove_tx_stream_data(crypto.data, crypto.acked_offset, offset + datalen);
 }
 
-int Client::on_stream_close(int64_t stream_id, uint16_t app_error_code) {
+int Client::on_stream_close(int64_t stream_id, uint64_t app_error_code) {
   auto it = streams_.find(stream_id);
 
   if (it == std::end(streams_)) {
diff --git a/examples/client.h b/examples/client.h
index acf65a8900469617130a3d4ec43c50e74405395e..0c9feab4c0719b789690701bdac87ad2418ec79b 100644
--- a/examples/client.h
+++ b/examples/client.h
@@ -205,7 +205,7 @@ public:
   int send_packet();
   void remove_tx_crypto_data(ngtcp2_crypto_level crypto_level, uint64_t offset,
                              size_t datalen);
-  int on_stream_close(int64_t stream_id, uint16_t app_error_code);
+  int on_stream_close(int64_t stream_id, uint64_t app_error_code);
   int on_extend_max_streams();
   int handle_error();
   void make_stream_early();
diff --git a/examples/server.cc b/examples/server.cc
index b400a4d6e5e12a23379786fcf62ce6717384f41a..cdff8b42321e7c4036a607cd8727c644fb0f62f6 100644
--- a/examples/server.cc
+++ b/examples/server.cc
@@ -1220,7 +1220,7 @@ int Handler::push_content(int64_t stream_id, const std::string &authority,
 }
 
 namespace {
-int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint16_t app_error_code,
+int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint64_t app_error_code,
                  void *user_data, void *stream_user_data) {
   auto h = static_cast<Handler *>(user_data);
   if (h->on_stream_close(stream_id, app_error_code) != 0) {
@@ -1232,7 +1232,7 @@ int stream_close(ngtcp2_conn *conn, int64_t stream_id, uint16_t app_error_code,
 
 namespace {
 int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
-                 uint16_t app_error_code, void *user_data,
+                 uint64_t app_error_code, void *user_data,
                  void *stream_user_data) {
   auto h = static_cast<Handler *>(user_data);
   if (h->on_stream_reset(stream_id) != 0) {
@@ -2486,7 +2486,7 @@ void Handler::remove_tx_crypto_data(ngtcp2_crypto_level crypto_level,
   ::remove_tx_stream_data(crypto.data, crypto.acked_offset, offset + datalen);
 }
 
-int Handler::on_stream_close(int64_t stream_id, uint16_t app_error_code) {
+int Handler::on_stream_close(int64_t stream_id, uint64_t app_error_code) {
   if (!config.quiet) {
     std::cerr << "QUIC stream " << stream_id << " closed" << std::endl;
   }
diff --git a/examples/server.h b/examples/server.h
index 275a871d7c90520b9f8144b326e9a83dd0bd190f..515dc9009afdc0b0b37c0e39865d26f0422dc425 100644
--- a/examples/server.h
+++ b/examples/server.h
@@ -242,7 +242,7 @@ public:
   void remove_tx_crypto_data(ngtcp2_crypto_level crypto_level, uint64_t offset,
                              size_t datalen);
   void on_stream_open(int64_t stream_id);
-  int on_stream_close(int64_t stream_id, uint16_t app_error_code);
+  int on_stream_close(int64_t stream_id, uint64_t app_error_code);
   void start_draining_period();
   int start_closing_period();
   bool draining() const;
diff --git a/examples/shared.cc b/examples/shared.cc
index 804f7547033f6e3a256e57bf37f6d98bf0f6d38e..b5c4c9a4b4c8998f21aa925f84b8f047716a5414 100644
--- a/examples/shared.cc
+++ b/examples/shared.cc
@@ -38,7 +38,7 @@ QUICError quic_err_transport(int liberr) {
 
 QUICError quic_err_tls(int alert) {
   return {QUICErrorType::Transport,
-          static_cast<uint16_t>(NGTCP2_CRYPTO_ERROR | alert)};
+          static_cast<uint64_t>(NGTCP2_CRYPTO_ERROR | alert)};
 }
 
 QUICError quic_err_app(int liberr) {
diff --git a/examples/shared.h b/examples/shared.h
index 4503d3dcb883307320c00303a821ad13ff0881ca..3e12d6c7a39cf9c246b294da74bd9c090a7ee0bd 100644
--- a/examples/shared.h
+++ b/examples/shared.h
@@ -33,9 +33,6 @@
 
 namespace ngtcp2 {
 
-constexpr uint16_t NGTCP2_APP_NOERROR = 0xff00;
-constexpr uint16_t NGTCP2_APP_PROTO = 0xff01;
-
 enum class QUICErrorType {
   Application,
   Transport,
@@ -43,10 +40,10 @@ enum class QUICErrorType {
 };
 
 struct QUICError {
-  QUICError(QUICErrorType type, uint16_t code) : type(type), code(code) {}
+  QUICError(QUICErrorType type, uint64_t code) : type(type), code(code) {}
 
   QUICErrorType type;
-  uint16_t code;
+  uint64_t code;
 };
 
 QUICError quic_err_transport(int liberr);
diff --git a/lib/includes/ngtcp2/ngtcp2.h b/lib/includes/ngtcp2/ngtcp2.h
index ffa40196dae5fdbe2652022a9fc440098b56a368..2f4da575cfcc5b8c79ec813af906d537caca3ddd 100644
--- a/lib/includes/ngtcp2/ngtcp2.h
+++ b/lib/includes/ngtcp2/ngtcp2.h
@@ -444,13 +444,13 @@ typedef struct {
 typedef struct {
   uint8_t type;
   int64_t stream_id;
-  uint16_t app_error_code;
+  uint64_t app_error_code;
   uint64_t final_size;
 } ngtcp2_reset_stream;
 
 typedef struct {
   uint8_t type;
-  uint16_t error_code;
+  uint64_t error_code;
   uint8_t frame_type;
   size_t reasonlen;
   uint8_t *reason;
@@ -506,7 +506,7 @@ typedef struct {
 typedef struct {
   uint8_t type;
   int64_t stream_id;
-  uint16_t app_error_code;
+  uint64_t app_error_code;
 } ngtcp2_stop_sending;
 
 typedef struct {
@@ -1244,7 +1244,7 @@ typedef int (*ngtcp2_stream_open)(ngtcp2_conn *conn, int64_t stream_id,
  * call return immediately.
  */
 typedef int (*ngtcp2_stream_close)(ngtcp2_conn *conn, int64_t stream_id,
-                                   uint16_t app_error_code, void *user_data,
+                                   uint64_t app_error_code, void *user_data,
                                    void *stream_user_data);
 
 /**
@@ -1258,7 +1258,7 @@ typedef int (*ngtcp2_stream_close)(ngtcp2_conn *conn, int64_t stream_id,
  * call return immediately.
  */
 typedef int (*ngtcp2_stream_reset)(ngtcp2_conn *conn, int64_t stream_id,
-                                   uint64_t final_size, uint16_t app_error_code,
+                                   uint64_t final_size, uint64_t app_error_code,
                                    void *user_data, void *stream_user_data);
 
 /**
@@ -2059,7 +2059,7 @@ NGTCP2_EXTERN int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn,
  */
 NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn,
                                               int64_t stream_id,
-                                              uint16_t app_error_code);
+                                              uint64_t app_error_code);
 
 /**
  * @function
@@ -2081,7 +2081,7 @@ NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn,
  */
 NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn,
                                                     int64_t stream_id,
-                                                    uint16_t app_error_code);
+                                                    uint64_t app_error_code);
 
 /**
  * @function
@@ -2102,7 +2102,7 @@ NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn,
  */
 NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn,
                                                    int64_t stream_id,
-                                                   uint16_t app_error_code);
+                                                   uint64_t app_error_code);
 
 /**
  * @enum
@@ -2275,7 +2275,7 @@ NGTCP2_EXTERN ssize_t ngtcp2_conn_writev_stream(
  */
 NGTCP2_EXTERN ssize_t ngtcp2_conn_write_connection_close(
     ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
-    uint16_t error_code, ngtcp2_tstamp ts);
+    uint64_t error_code, ngtcp2_tstamp ts);
 
 /**
  * @function
@@ -2310,7 +2310,7 @@ NGTCP2_EXTERN ssize_t ngtcp2_conn_write_connection_close(
  */
 NGTCP2_EXTERN ssize_t ngtcp2_conn_write_application_close(
     ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
-    uint16_t app_error_code, ngtcp2_tstamp ts);
+    uint64_t app_error_code, ngtcp2_tstamp ts);
 
 /**
  * @function
@@ -2560,7 +2560,7 @@ NGTCP2_EXTERN int ngtcp2_err_is_fatal(int liberr);
  * `ngtcp2_err_infer_quic_transport_error_code` returns a QUIC
  * transport error code which corresponds to |liberr|.
  */
-NGTCP2_EXTERN uint16_t ngtcp2_err_infer_quic_transport_error_code(int liberr);
+NGTCP2_EXTERN uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr);
 
 /**
  * @function
diff --git a/lib/ngtcp2_conn.c b/lib/ngtcp2_conn.c
index b123415a3b8cef971865e9ad069c3653496efdff..3abd5feb3aa0c14b70e0a2a3e643d75ec560dd6d 100644
--- a/lib/ngtcp2_conn.c
+++ b/lib/ngtcp2_conn.c
@@ -133,7 +133,7 @@ static int conn_call_stream_open(ngtcp2_conn *conn, ngtcp2_strm *strm) {
 }
 
 static int conn_call_stream_close(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                                  uint16_t app_error_code) {
+                                  uint64_t app_error_code) {
   int rv;
 
   if (!conn->callbacks.stream_close) {
@@ -150,7 +150,7 @@ static int conn_call_stream_close(ngtcp2_conn *conn, ngtcp2_strm *strm,
 }
 
 static int conn_call_stream_reset(ngtcp2_conn *conn, int64_t stream_id,
-                                  uint64_t final_size, uint16_t app_error_code,
+                                  uint64_t final_size, uint64_t app_error_code,
                                   void *stream_user_data) {
   int rv;
 
@@ -5005,7 +5005,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
  *     Out of memory.
  */
 static int conn_reset_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                             uint16_t app_error_code) {
+                             uint64_t app_error_code) {
   int rv;
   ngtcp2_frame_chain *frc;
   ngtcp2_pktns *pktns = &conn->pktns;
@@ -5038,7 +5038,7 @@ static int conn_reset_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
  *     Out of memory.
  */
 static int conn_stop_sending(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                             uint16_t app_error_code) {
+                             uint64_t app_error_code) {
   int rv;
   ngtcp2_frame_chain *frc;
   ngtcp2_pktns *pktns = &conn->pktns;
@@ -7800,7 +7800,7 @@ ssize_t ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
 
 ssize_t ngtcp2_conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_path *path,
                                            uint8_t *dest, size_t destlen,
-                                           uint16_t error_code,
+                                           uint64_t error_code,
                                            ngtcp2_tstamp ts) {
   ssize_t res, nwrite;
   ngtcp2_frame fr;
@@ -7866,7 +7866,7 @@ ssize_t ngtcp2_conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_path *path,
 ssize_t ngtcp2_conn_write_application_close(ngtcp2_conn *conn,
                                             ngtcp2_path *path, uint8_t *dest,
                                             size_t destlen,
-                                            uint16_t app_error_code,
+                                            uint64_t app_error_code,
                                             ngtcp2_tstamp ts) {
   ssize_t nwrite;
   ngtcp2_frame fr;
@@ -7914,7 +7914,7 @@ int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn) {
 }
 
 int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                             uint16_t app_error_code) {
+                             uint64_t app_error_code) {
   int rv;
 
   if (!strm->app_error_code) {
@@ -7953,7 +7953,7 @@ fin:
 }
 
 int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                                          uint16_t app_error_code) {
+                                          uint64_t app_error_code) {
   if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RDWR) ==
           NGTCP2_STRM_FLAG_SHUT_RDWR &&
       ((strm->flags & NGTCP2_STRM_FLAG_RECV_RST) ||
@@ -7978,7 +7978,7 @@ int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm,
  *     Out of memory.
  */
 static int conn_shutdown_stream_write(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                                      uint16_t app_error_code) {
+                                      uint64_t app_error_code) {
   if (strm->flags & NGTCP2_STRM_FLAG_SENT_RST) {
     return 0;
   }
@@ -8004,7 +8004,7 @@ static int conn_shutdown_stream_write(ngtcp2_conn *conn, ngtcp2_strm *strm,
  *     Out of memory.
  */
 static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                                     uint16_t app_error_code) {
+                                     uint64_t app_error_code) {
   if (strm->flags &
       (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)) {
     return 0;
@@ -8017,7 +8017,7 @@ static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm,
 }
 
 int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, int64_t stream_id,
-                                uint16_t app_error_code) {
+                                uint64_t app_error_code) {
   int rv;
   ngtcp2_strm *strm;
 
@@ -8040,7 +8040,7 @@ int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, int64_t stream_id,
 }
 
 int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, int64_t stream_id,
-                                      uint16_t app_error_code) {
+                                      uint64_t app_error_code) {
   ngtcp2_strm *strm;
 
   strm = ngtcp2_conn_find_stream(conn, stream_id);
@@ -8052,7 +8052,7 @@ int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, int64_t stream_id,
 }
 
 int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, int64_t stream_id,
-                                     uint16_t app_error_code) {
+                                     uint64_t app_error_code) {
   ngtcp2_strm *strm;
 
   strm = ngtcp2_conn_find_stream(conn, stream_id);
diff --git a/lib/ngtcp2_conn.h b/lib/ngtcp2_conn.h
index 36c97b1915062bb272befc2596c3516684ec850f..fc27b2fa11add5120c00719878b2ddb7b23d913b 100644
--- a/lib/ngtcp2_conn.h
+++ b/lib/ngtcp2_conn.h
@@ -616,7 +616,7 @@ int ngtcp2_conn_init_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
  *     User-defined callback function failed.
  */
 int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                             uint16_t app_error_code);
+                             uint64_t app_error_code);
 
 /*
  * ngtcp2_conn_close_stream closes stream |strm| if no further
@@ -633,7 +633,7 @@ int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
  *     User-defined callback function failed.
  */
 int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm,
-                                          uint16_t app_error_code);
+                                          uint64_t app_error_code);
 
 /*
  * ngtcp2_conn_update_rtt updates RTT measurements.  |rtt| is a latest
diff --git a/lib/ngtcp2_err.c b/lib/ngtcp2_err.c
index 3d324ea24fa3ca2fb905b912fd1effed53691968..a40fa9eecce79d4ffa3e97e8ad5ec82678c8b078 100644
--- a/lib/ngtcp2_err.c
+++ b/lib/ngtcp2_err.c
@@ -105,7 +105,7 @@ const char *ngtcp2_strerror(int liberr) {
 
 int ngtcp2_err_is_fatal(int liberr) { return liberr < NGTCP2_ERR_FATAL; }
 
-uint16_t ngtcp2_err_infer_quic_transport_error_code(int liberr) {
+uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr) {
   switch (liberr) {
   case 0:
     return NGTCP2_NO_ERROR;
diff --git a/lib/ngtcp2_log.c b/lib/ngtcp2_log.c
index 3d6096ac8588dd8d33f502a338970860bceb047c..b9d5e6273253164e2f465482063cbd3e5452ee32 100644
--- a/lib/ngtcp2_log.c
+++ b/lib/ngtcp2_log.c
@@ -108,7 +108,7 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid,
 #define NGTCP2_LOG_TP_HD_FIELDS                                                \
   timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "cry"
 
-static const char *strerrorcode(uint16_t error_code) {
+static const char *strerrorcode(uint64_t error_code) {
   switch (error_code) {
   case NGTCP2_NO_ERROR:
     return "NO_ERROR";
@@ -140,7 +140,7 @@ static const char *strerrorcode(uint16_t error_code) {
   }
 }
 
-static const char *strapperrorcode(uint16_t app_error_code) {
+static const char *strapperrorcode(uint64_t app_error_code) {
   (void)app_error_code;
   return "(unknown)";
 }
@@ -247,12 +247,13 @@ static void log_fr_padding(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
 static void log_fr_reset_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                                 const ngtcp2_reset_stream *fr,
                                 const char *dir) {
-  log->log_printf(
-      log->user_data,
-      (NGTCP2_LOG_PKT " RESET_STREAM(0x%02x) id=0x%" PRIx64
-                      " app_error_code=%s(0x%04x) final_size=%" PRIu64 "\n"),
-      NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
-      strapperrorcode(fr->app_error_code), fr->app_error_code, fr->final_size);
+  log->log_printf(log->user_data,
+                  (NGTCP2_LOG_PKT " RESET_STREAM(0x%02x) id=0x%" PRIx64
+                                  " app_error_code=%s(0x%" PRIx64
+                                  ") final_size=%" PRIu64 "\n"),
+                  NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
+                  strapperrorcode(fr->app_error_code), fr->app_error_code,
+                  fr->final_size);
 }
 
 static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
@@ -260,7 +261,7 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                                     const char *dir) {
   log->log_printf(log->user_data,
                   (NGTCP2_LOG_PKT
-                   " CONNECTION_CLOSE(0x%02x) error_code=%s(0x%04x) "
+                   " CONNECTION_CLOSE(0x%02x) error_code=%s(0x%" PRIx64 ") "
                    "frame_type=%u reason_len=%" PRIu64 "\n"),
                   NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type,
                   fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
@@ -347,7 +348,7 @@ static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
                                 const char *dir) {
   log->log_printf(log->user_data,
                   (NGTCP2_LOG_PKT " STOP_SENDING(0x%02x) id=0x%" PRIx64
-                                  " app_error_code=%s(0x%04x)\n"),
+                                  " app_error_code=%s(0x%" PRIx64 ")\n"),
                   NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
                   strapperrorcode(fr->app_error_code), fr->app_error_code);
 }
diff --git a/lib/ngtcp2_pkt.c b/lib/ngtcp2_pkt.c
index 44206366d90314843f84a4bb21b09046cded78dd..2f5fd60193cbd0ec5d42807b55ee98cd31e38a67 100644
--- a/lib/ngtcp2_pkt.c
+++ b/lib/ngtcp2_pkt.c
@@ -687,7 +687,7 @@ size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest,
 ssize_t ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
                                              const uint8_t *payload,
                                              size_t payloadlen) {
-  size_t len = 1 + 1 + 2 + 1;
+  size_t len = 1 + 1 + 1 + 1;
   const uint8_t *p;
   size_t n;
 
@@ -702,7 +702,13 @@ ssize_t ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
   if (payloadlen < len) {
     return NGTCP2_ERR_FRAME_ENCODING;
   }
-  p += n + 2;
+  p += n;
+  n = ngtcp2_get_varint_len(p);
+  len += n - 1;
+  if (payloadlen < len) {
+    return NGTCP2_ERR_FRAME_ENCODING;
+  }
+  p += n;
   n = ngtcp2_get_varint_len(p);
   len += n - 1;
   if (payloadlen < len) {
@@ -714,8 +720,8 @@ ssize_t ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
   dest->type = NGTCP2_FRAME_RESET_STREAM;
   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
   p += n;
-  dest->app_error_code = ngtcp2_get_uint16(p);
-  p += 2;
+  dest->app_error_code = ngtcp2_get_varint(&n, p);
+  p += n;
   dest->final_size = ngtcp2_get_varint(&n, p);
   p += n;
 
@@ -727,7 +733,7 @@ ssize_t ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
 ssize_t ngtcp2_pkt_decode_connection_close_frame(ngtcp2_connection_close *dest,
                                                  const uint8_t *payload,
                                                  size_t payloadlen) {
-  size_t len = 1 + 2 + 1;
+  size_t len = 1 + 1 + 1;
   const uint8_t *p;
   size_t reasonlen;
   size_t nreasonlen;
@@ -741,7 +747,15 @@ ssize_t ngtcp2_pkt_decode_connection_close_frame(ngtcp2_connection_close *dest,
 
   type = payload[0];
 
-  p = payload + 1 + 2;
+  p = payload + 1;
+
+  n = ngtcp2_get_varint_len(p);
+  len += n - 1;
+  if (payloadlen < len) {
+    return NGTCP2_ERR_FRAME_ENCODING;
+  }
+
+  p += n;
 
   if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
     ++len;
@@ -771,8 +785,8 @@ ssize_t ngtcp2_pkt_decode_connection_close_frame(ngtcp2_connection_close *dest,
   p = payload + 1;
 
   dest->type = type;
-  dest->error_code = ngtcp2_get_uint16(p);
-  p += 2;
+  dest->error_code = ngtcp2_get_varint(&n, p);
+  p += n;
   if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
     frame_type = ngtcp2_get_varint(&n, p);
     /* TODO Ignore large frame type for now */
@@ -1070,7 +1084,7 @@ ssize_t ngtcp2_pkt_decode_new_connection_id_frame(
 ssize_t ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest,
                                              const uint8_t *payload,
                                              size_t payloadlen) {
-  size_t len = 1 + 1 + 2;
+  size_t len = 1 + 1 + 1;
   const uint8_t *p;
   size_t n;
 
@@ -1086,12 +1100,21 @@ ssize_t ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest,
   if (payloadlen < len) {
     return NGTCP2_ERR_FRAME_ENCODING;
   }
+  p += n;
+  n = ngtcp2_get_varint_len(p);
+  len += n - 1;
+
+  if (payloadlen < len) {
+    return NGTCP2_ERR_FRAME_ENCODING;
+  }
+
+  p = payload + 1;
 
   dest->type = NGTCP2_FRAME_STOP_SENDING;
   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
   p += n;
-  dest->app_error_code = ngtcp2_get_uint16(p);
-  p += 2;
+  dest->app_error_code = ngtcp2_get_varint(&n, p);
+  p += n;
 
   assert((size_t)(p - payload) == len);
 
@@ -1431,7 +1454,8 @@ ssize_t ngtcp2_pkt_encode_padding_frame(uint8_t *out, size_t outlen,
 
 ssize_t ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
                                              const ngtcp2_reset_stream *fr) {
-  size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) + 2 +
+  size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
+               ngtcp2_put_varint_len(fr->app_error_code) +
                ngtcp2_put_varint_len(fr->final_size);
   uint8_t *p;
 
@@ -1443,7 +1467,7 @@ ssize_t ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
 
   *p++ = NGTCP2_FRAME_RESET_STREAM;
   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
-  p = ngtcp2_put_uint16be(p, fr->app_error_code);
+  p = ngtcp2_put_varint(p, fr->app_error_code);
   p = ngtcp2_put_varint(p, fr->final_size);
 
   assert((size_t)(p - out) == len);
@@ -1454,7 +1478,7 @@ ssize_t ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
 ssize_t
 ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen,
                                          const ngtcp2_connection_close *fr) {
-  size_t len = 1 + 2 +
+  size_t len = 1 + ngtcp2_put_varint_len(fr->error_code) +
                (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
                     ? ngtcp2_put_varint_len(fr->frame_type)
                     : 0) +
@@ -1468,7 +1492,7 @@ ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen,
   p = out;
 
   *p++ = fr->type;
-  p = ngtcp2_put_uint16be(p, fr->error_code);
+  p = ngtcp2_put_varint(p, fr->error_code);
   if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) {
     p = ngtcp2_put_varint(p, fr->frame_type);
   }
@@ -1644,7 +1668,9 @@ ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen,
 
 ssize_t ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen,
                                              const ngtcp2_stop_sending *fr) {
-  size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) + 2;
+  size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
+               ngtcp2_put_varint_len(fr->app_error_code);
+  ;
   uint8_t *p;
 
   if (outlen < len) {
@@ -1655,7 +1681,7 @@ ssize_t ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen,
 
   *p++ = NGTCP2_FRAME_STOP_SENDING;
   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
-  p = ngtcp2_put_uint16be(p, fr->app_error_code);
+  p = ngtcp2_put_varint(p, fr->app_error_code);
 
   assert((size_t)(p - out) == len);
 
diff --git a/lib/ngtcp2_strm.c b/lib/ngtcp2_strm.c
index cb2ea0013670699bf6404dce12929b4a427f499d..00723eb3296557fa41584ae3907fd34f693160d0 100644
--- a/lib/ngtcp2_strm.c
+++ b/lib/ngtcp2_strm.c
@@ -53,11 +53,6 @@ int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
   strm->me.next = NULL;
   strm->pe.index = NGTCP2_PQ_BAD_INDEX;
   strm->mem = mem;
-  /* Initializing to 0 is a bit controversial because application
-     error code 0 is STOPPING.  But STOPPING is only sent with
-     RST_STREAM in response to STOP_SENDING, and it is not used to
-     indicate the cause of closure.  So effectively, 0 means "no
-     error." */
   strm->app_error_code = 0;
 
   rv = ngtcp2_gaptr_init(&strm->tx.acked_offset, mem);
diff --git a/lib/ngtcp2_strm.h b/lib/ngtcp2_strm.h
index 9d80c6ee99bc1ff3e6667f8132e95ae1e3c6a32e..67d49e519e0eda5f86bffc6bd93a02d4e945dbf1 100644
--- a/lib/ngtcp2_strm.h
+++ b/lib/ngtcp2_strm.h
@@ -115,7 +115,7 @@ struct ngtcp2_strm {
   uint32_t flags;
   /* app_error_code is an error code the local endpoint sent in
      RST_STREAM or STOP_SENDING. */
-  uint16_t app_error_code;
+  uint64_t app_error_code;
 };
 
 /*
diff --git a/tests/ngtcp2_pkt_test.c b/tests/ngtcp2_pkt_test.c
index 518bc0d46d4abe1a512dc920dc96b68bd16a2925..5445fcf42d2427510ec6206d69f72c9087ea909f 100644
--- a/tests/ngtcp2_pkt_test.c
+++ b/tests/ngtcp2_pkt_test.c
@@ -521,7 +521,7 @@ void test_ngtcp2_pkt_encode_reset_stream_frame(void) {
   uint8_t buf[32];
   ngtcp2_reset_stream fr, nfr;
   ssize_t rv;
-  size_t framelen = 1 + 4 + 2 + 8;
+  size_t framelen = 1 + 4 + 4 + 8;
 
   fr.type = NGTCP2_FRAME_RESET_STREAM;
   fr.stream_id = 1000000007;
@@ -557,7 +557,7 @@ void test_ngtcp2_pkt_encode_connection_close_frame(void) {
   fr.connection_close.reasonlen = 0;
   fr.connection_close.reason = NULL;
 
-  framelen = 1 + 2 + 2 + 1;
+  framelen = 1 + 4 + 2 + 1;
 
   rv = ngtcp2_pkt_encode_connection_close_frame(buf, sizeof(buf),
                                                 &fr.connection_close);
@@ -582,7 +582,7 @@ void test_ngtcp2_pkt_encode_connection_close_frame(void) {
   fr.connection_close.reasonlen = sizeof(reason);
   fr.connection_close.reason = reason;
 
-  framelen = 1 + 2 + 1 + 2 + sizeof(reason);
+  framelen = 1 + 4 + 1 + 2 + sizeof(reason);
 
   rv = ngtcp2_pkt_encode_connection_close_frame(buf, sizeof(buf),
                                                 &fr.connection_close);
@@ -617,7 +617,7 @@ void test_ngtcp2_pkt_encode_connection_close_app_frame(void) {
   fr.connection_close.reasonlen = 0;
   fr.connection_close.reason = NULL;
 
-  framelen = 1 + 2 + 1;
+  framelen = 1 + 4 + 1;
 
   rv = ngtcp2_pkt_encode_connection_close_frame(buf, sizeof(buf),
                                                 &fr.connection_close);
@@ -811,7 +811,7 @@ void test_ngtcp2_pkt_encode_stop_sending_frame(void) {
   uint8_t buf[16];
   ngtcp2_stop_sending fr, nfr;
   ssize_t rv;
-  size_t framelen = 1 + 8 + 2;
+  size_t framelen = 1 + 8 + 4;
 
   fr.type = NGTCP2_FRAME_STOP_SENDING;
   fr.stream_id = 0xf1f2f3f4u;