Commit 6e4ab854 for whisper.cpp

commit 6e4ab854f67f743900934a703d5603419384c961
Author: Vincenzo Reina <vincenzoreinaa05@gmail.com>
Date:   Mon Sep 28 19:35:45 2026 +0100

    cli : fix incorrect error code when files are failing (#4080)

    * cli : fix incorrect error code when file are failing

    * cli : add whisper_free before returning error

diff --git a/examples/cli/cli.cpp b/examples/cli/cli.cpp
index 55d5d433..b015319d 100644
--- a/examples/cli/cli.cpp
+++ b/examples/cli/cli.cpp
@@ -1011,12 +1011,16 @@ int main(int argc, char ** argv) {
         return 1;
     }

+    // number of input files that could not be processed or whose output could not be written
+    int n_failed = 0;
+
     // remove non-existent files
     for (auto it = params.fname_inp.begin(); it != params.fname_inp.end();) {
         const auto fname_inp = it->c_str();

         if (*it != "-" && !is_file_exist(fname_inp)) {
             fprintf(stderr, "error: input file not found '%s'\n", fname_inp);
+            n_failed++;
             it = params.fname_inp.erase(it);
             continue;
         }
@@ -1124,6 +1128,7 @@ int main(int argc, char ** argv) {
             const size_t basename_length;
             const bool is_stdout;
             bool used_stdout;
+            bool failed;
             decltype(whisper_print_segment_callback) * const print_segment_callback;
             std::ofstream fout;

@@ -1132,6 +1137,7 @@ int main(int argc, char ** argv) {
                     basename_length{fname_out.size()},
                     is_stdout{fname_out == "-"},
                     used_stdout{},
+                    failed{},
                     print_segment_callback{is_stdout ? nullptr : whisper_print_segment_callback} {
                 if (!print_segment_callback) {
                     params.print_progress = false;
@@ -1161,6 +1167,7 @@ int main(int argc, char ** argv) {
                 fout = std::ofstream{fname_out};
                 if (!fout.is_open()) {
                     fprintf(stderr, "%s: failed to open '%s' for writing\n", __func__, fname_out.c_str());
+                    failed = true;
                     return false;
                 }
                 fprintf(stderr, "%s: saving output to '%s'\n", function, fname_out.c_str());
@@ -1173,6 +1180,7 @@ int main(int argc, char ** argv) {

         if (!::read_audio_data(fname_inp, pcmf32, pcmf32s, params.diarize)) {
             fprintf(stderr, "error: failed to read audio file '%s'\n", fname_inp.c_str());
+            n_failed++;
             continue;
         }

@@ -1323,6 +1331,7 @@ int main(int argc, char ** argv) {

             if (whisper_full_parallel(ctx, wparams, pcmf32.data(), pcmf32.size(), params.n_processors) != 0) {
                 fprintf(stderr, "%s: failed to process audio\n", argv[0]);
+                whisper_free(ctx);
                 return 10;
             }
         }
@@ -1351,6 +1360,10 @@ int main(int argc, char ** argv) {
                 fprintf(stderr, "warning: '--output-file -' used without any other '--output-*'");
             }
         }
+
+        if (fout_factory.failed) {
+            n_failed++;
+        }
     }

     if (!params.no_prints) {
@@ -1358,5 +1371,10 @@ int main(int argc, char ** argv) {
     }
     whisper_free(ctx);

+    if (n_failed > 0) {
+        fprintf(stderr, "error: %d input file(s) failed\n", n_failed);
+        return 11;
+    }
+
     return 0;
 }
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index ab4acfac..9c055701 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -22,6 +22,23 @@ add_test(NAME ${TEST_TARGET}
     -f ${PROJECT_SOURCE_DIR}/samples/jfk.wav)
 set_tests_properties(${TEST_TARGET} PROPERTIES LABELS "tiny;gh")

+# whisper-cli must exit with non-zero status when an input cannot be decoded (#4011)
+set(TEST_TARGET test-whisper-cli-bad-audio)
+add_test(NAME ${TEST_TARGET}
+    COMMAND $<TARGET_FILE:whisper-cli>
+    -m ${PROJECT_SOURCE_DIR}/models/for-tests-ggml-tiny.bin
+    -f ${PROJECT_SOURCE_DIR}/README.md)
+set_tests_properties(${TEST_TARGET} PROPERTIES LABELS "tiny;gh" WILL_FAIL TRUE)
+
+# whisper-cli must exit with non-zero status when an output file cannot be written (#4011)
+set(TEST_TARGET test-whisper-cli-bad-output)
+add_test(NAME ${TEST_TARGET}
+    COMMAND $<TARGET_FILE:whisper-cli>
+    -m ${PROJECT_SOURCE_DIR}/models/for-tests-ggml-tiny.bin
+    -f ${PROJECT_SOURCE_DIR}/samples/jfk.wav
+    -otxt -of ${CMAKE_CURRENT_BINARY_DIR}/non-existent-dir/out)
+set_tests_properties(${TEST_TARGET} PROPERTIES LABELS "tiny;gh" WILL_FAIL TRUE)
+
 set(TEST_TARGET test-whisper-cli-tiny.en)
 add_test(NAME ${TEST_TARGET}
     COMMAND $<TARGET_FILE:whisper-cli>