diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index e671a572a8..12c22184a3 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -375,19 +375,22 @@ static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv
     return 0;
 }
 
-static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp,
+static int end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp,
                                   MatroskaMuxContext *mkv, uint32_t id,
                                   int length_size, int keep_buffer,
                                   int add_seekentry)
 {
     uint8_t *buf, crc[4];
-    int size, skip = 0;
+    int ret, size, skip = 0;
+
+    size = avio_get_dyn_buf(*dyn_cp, &buf);
+    if ((ret = (*dyn_cp)->error) < 0)
+        goto fail;
 
     if (add_seekentry)
         mkv_add_seekhead_entry(mkv, id, avio_tell(pb));
 
     put_ebml_id(pb, id);
-    size = avio_get_dyn_buf(*dyn_cp, &buf);
     put_ebml_length(pb, size, length_size);
     if (mkv->write_crc) {
         skip = 6; /* Skip reserved 6-byte long void element from the dynamic buffer. */
@@ -396,18 +399,20 @@ static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp,
     }
     avio_write(pb, buf + skip, size - skip);
 
+fail:
     if (keep_buffer) {
         ffio_reset_dyn_buf(*dyn_cp);
     } else {
         ffio_free_dyn_buf(dyn_cp);
     }
+    return ret;
 }
 
 /**
  * Output EBML master. Keep the buffer if seekable, allowing for later updates.
  * Furthermore always add a SeekHead Entry for this element.
  */
-static void end_ebml_master_crc32_tentatively(AVIOContext *pb,
+static int end_ebml_master_crc32_tentatively(AVIOContext *pb,
                                               ebml_stored_master *elem,
                                               MatroskaMuxContext *mkv, uint32_t id)
 {
@@ -415,14 +420,19 @@ static void end_ebml_master_crc32_tentatively(AVIOContext *pb,
     uint8_t *buf;
         int size = avio_get_dyn_buf(elem->bc, &buf);
 
+        if (elem->bc->error < 0)
+            return elem->bc->error;
+
         elem->pos = avio_tell(pb);
         mkv_add_seekhead_entry(mkv, id, elem->pos);
 
     put_ebml_id(pb, id);
     put_ebml_length(pb, size, 0);
     avio_write(pb, buf, size);
+
+        return 0;
     } else
-        end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1);
+        return end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1);
 }
 
 static void put_xiph_size(AVIOContext *pb, int size)
@@ -501,7 +511,10 @@ static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv,
         put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);
         end_ebml_master(dyn_cp, seekentry);
     }
-    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD, 0, 0, 0);
+    ret = end_ebml_master_crc32(pb, &dyn_cp, mkv,
+                                MATROSKA_ID_SEEKHEAD, 0, 0, 0);
+    if (ret < 0)
+        return ret;
 
     remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb);
     put_ebml_void(pb, remaining);
@@ -574,12 +587,14 @@ static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp,
             end_ebml_master(cuepoint, track_positions);
         } while (++entry < end && entry->pts == pts);
         size = avio_get_dyn_buf(cuepoint, &buf);
+        if ((ret = cuepoint->error) < 0)
+            break;
         put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size);
         ffio_reset_dyn_buf(cuepoint);
     }
     ffio_free_dyn_buf(&cuepoint);
 
-    return 0;
+    return ret;
 }
 
 static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb,
@@ -800,10 +815,12 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
         ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
     }
 
+    if (ret >= 0) {
     codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv);
-    if (codecpriv_size)
+        if ((ret = dyn_cp->error) >= 0 && codecpriv_size)
         put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv,
                         codecpriv_size);
+    }
     ffio_free_dyn_buf(&dyn_cp);
     return ret;
 }
@@ -1423,10 +1440,8 @@ static int mkv_write_tracks(AVFormatContext *s)
             return ret;
     }
 
-    end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv,
+    return end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv,
                                       MATROSKA_ID_TRACKS);
-
-    return 0;
 }
 
 static int mkv_write_chapters(AVFormatContext *s)
@@ -1482,10 +1497,10 @@ static int mkv_write_chapters(AVFormatContext *s)
         end_ebml_master(dyn_cp, chapteratom);
     }
     end_ebml_master(dyn_cp, editionentry);
-    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0, 1);
-
     mkv->wrote_chapters = 1;
-    return 0;
+
+    return end_ebml_master_crc32(pb, &dyn_cp, mkv,
+                                 MATROSKA_ID_CHAPTERS, 0, 0, 1);
 }
 
 static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t)
@@ -1677,7 +1692,7 @@ static int mkv_write_tags(AVFormatContext *s)
     }
 
     if (mkv->tags.bc) {
-        end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv,
+        return end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv,
                                           MATROSKA_ID_TAGS);
     }
     return 0;
@@ -1740,9 +1755,8 @@ static int mkv_write_attachments(AVFormatContext *s)
         put_ebml_uid(dyn_cp, MATROSKA_ID_FILEUID, track->uid);
         end_ebml_master(dyn_cp, attached_file);
     }
-    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0, 1);
-
-    return 0;
+    return end_ebml_master_crc32(pb, &dyn_cp, mkv,
+                                 MATROSKA_ID_ATTACHMENTS, 0, 0, 1);
 }
 
 static int64_t get_metadata_duration(AVFormatContext *s)
@@ -1856,7 +1870,10 @@ static int mkv_write_header(AVFormatContext *s)
             put_ebml_void(pb, 11);              // assumes double-precision float to be written
         }
     }
-    end_ebml_master_crc32_tentatively(s->pb, &mkv->info, mkv, MATROSKA_ID_INFO);
+    ret = end_ebml_master_crc32_tentatively(s->pb, &mkv->info,
+                                            mkv, MATROSKA_ID_INFO);
+    if (ret < 0)
+        return ret;
     pb = s->pb;
 
     ret = mkv_write_tracks(s);
@@ -2137,18 +2154,23 @@ static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, const AVPac
     return pkt->duration;
 }
 
-static void mkv_end_cluster(AVFormatContext *s)
+static int mkv_end_cluster(AVFormatContext *s)
 {
     MatroskaMuxContext *mkv = s->priv_data;
+    int ret;
 
-    end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv,
-                          MATROSKA_ID_CLUSTER, 0, 1, 0);
     if (!mkv->have_video) {
         for (unsigned i = 0; i < s->nb_streams; i++)
             mkv->tracks[i].has_cue = 0;
     }
     mkv->cluster_pos = -1;
+    ret = end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv,
+                                MATROSKA_ID_CLUSTER, 0, 1, 0);
+    if (ret < 0)
+        return ret;
+
     avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
+    return 0;
 }
 
 static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
@@ -2216,15 +2238,16 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
             if (ret < 0)
                 return ret;
             ff_isom_write_av1c(dyn_cp, side_data, side_data_size);
-            codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv);
-            if (!codecpriv_size) {
-                av_free(codecpriv);
-                return AVERROR_INVALIDDATA;
+            codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv);
+            if ((ret = dyn_cp->error) < 0 ||
+                !codecpriv_size && (ret = AVERROR_INVALIDDATA)) {
+                ffio_free_dyn_buf(&dyn_cp);
+                return ret;
             }
             avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET);
             // Do not write the OBUs as we don't have space saved for them
             put_ebml_binary(mkv->track.bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4);
-            av_free(codecpriv);
+            ffio_free_dyn_buf(&dyn_cp);
             ret = ff_alloc_extradata(par, side_data_size);
             if (ret < 0)
                 return ret;
@@ -2262,7 +2285,9 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt)
     if (mkv->cluster_pos != -1) {
         int64_t cluster_time = ts - mkv->cluster_pts;
         if ((int16_t)cluster_time != cluster_time) {
-            mkv_end_cluster(s);
+            ret = mkv_end_cluster(s);
+            if (ret < 0)
+                return ret;
             av_log(s, AV_LOG_WARNING, "Starting new cluster due to timestamp\n");
         }
     }
@@ -2372,8 +2397,11 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt)
         } else
             start_new_cluster = 0;
 
-        if (start_new_cluster)
-            mkv_end_cluster(s);
+        if (start_new_cluster) {
+            ret = mkv_end_cluster(s);
+            if (ret < 0)
+                return ret;
+        }
     }
 
     if (!mkv->cluster_pos)
@@ -2408,7 +2436,9 @@ static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt)
 
     if (!pkt) {
         if (mkv->cluster_pos != -1) {
-            mkv_end_cluster(s);
+            int ret = mkv_end_cluster(s);
+            if (ret < 0)
+                return ret;
             av_log(s, AV_LOG_DEBUG,
                    "Flushing cluster at offset %" PRIu64 " bytes\n",
                    avio_tell(s->pb));
@@ -2435,8 +2465,10 @@ static int mkv_write_trailer(AVFormatContext *s)
     }
 
     if (mkv->cluster_bc) {
-        end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv,
+        ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv,
                               MATROSKA_ID_CLUSTER, 0, 0, 0);
+        if (ret < 0)
+            return ret;
     }
 
     ret = mkv_write_chapters(s);
@@ -2493,8 +2525,10 @@ static int mkv_write_trailer(AVFormatContext *s)
                     }
                 }
             }
-            end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES,
+            ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES,
                                   length_size, 0, 1);
+            if (ret < 0)
+                return ret;
             if (mkv->reserve_cues_space) {
                 if (size < mkv->reserve_cues_space)
                     put_ebml_void(pb, mkv->reserve_cues_space - size);
@@ -2511,13 +2545,18 @@ static int mkv_write_trailer(AVFormatContext *s)
         av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration);
         avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET);
         put_ebml_float(mkv->info.bc, MATROSKA_ID_DURATION, mkv->duration);
-        end_ebml_master_crc32(pb, &mkv->info.bc, mkv, MATROSKA_ID_INFO, 0, 0, 0);
+        ret = end_ebml_master_crc32(pb, &mkv->info.bc, mkv,
+                                    MATROSKA_ID_INFO, 0, 0, 0);
+        if (ret < 0)
+            return ret;
 
         if (mkv->track.bc) {
             // write Tracks master
             avio_seek(pb, mkv->track.pos, SEEK_SET);
-            end_ebml_master_crc32(pb, &mkv->track.bc, mkv,
+            ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv,
                                   MATROSKA_ID_TRACKS, 0, 0, 0);
+            if (ret < 0)
+                return ret;
         }
 
         // update stream durations
@@ -2545,8 +2584,10 @@ static int mkv_write_trailer(AVFormatContext *s)
             }
 
             avio_seek(pb, mkv->tags.pos, SEEK_SET);
-            end_ebml_master_crc32(pb, &mkv->tags.bc, mkv,
+            ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv,
                                   MATROSKA_ID_TAGS, 0, 0, 0);
+            if (ret < 0)
+                return ret;
         }
 
         avio_seek(pb, endpos, SEEK_SET);
