diff --git a/bisect.c b/bisect.c
index 888949fba6..9e6a2b7f20 100644
--- a/bisect.c
+++ b/bisect.c
@@ -724,7 +724,8 @@ static int is_expected_rev(const struct object_id *oid)
 	return res;
 }

-static enum bisect_error bisect_checkout(const struct object_id *bisect_rev, int no_checkout)
+enum bisect_error bisect_checkout(const struct object_id *bisect_rev,
+				  int no_checkout)
 {
 	char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
 	struct commit *commit;
diff --git a/bisect.h b/bisect.h
index ec24ac2d7e..748adf0cff 100644
--- a/bisect.h
+++ b/bisect.h
@@ -69,4 +69,7 @@ void read_bisect_terms(const char **bad, const char **good);

 int bisect_clean_state(void);

+enum bisect_error bisect_checkout(const struct object_id *bisect_rev,
+				  int no_checkout);
+
 #endif
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index e529665d9f..50783a586c 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -1089,6 +1089,44 @@ static int bisect_visualize(struct bisect_terms *terms, const char **argv, int a
 	return res;
 }

+static int get_first_good(const char *refname, const struct object_id *oid,
+			  int flag, void *cb_data)
+{
+	oidcpy(cb_data, oid);
+	return 1;
+}
+
+static int verify_good(const struct bisect_terms *terms,
+		       const char **quoted_argv)
+{
+	int rc;
+	enum bisect_error res;
+	struct object_id good_rev;
+	struct object_id current_rev;
+	char *good_glob = xstrfmt("%s-*", terms->term_good);
+	int no_checkout = ref_exists("BISECT_HEAD");
+
+	for_each_glob_ref_in(get_first_good, good_glob, "refs/bisect/",
+			     &good_rev);
+	free(good_glob);
+
+	if (read_ref(no_checkout ? "BISECT_HEAD" : "HEAD", &current_rev))
+		return -1;
+
+	res = bisect_checkout(&good_rev, no_checkout);
+	if (res != BISECT_OK)
+		return -1;
+
+	printf(_("running %s\n"), quoted_argv[0]);
+	rc = run_command_v_opt(quoted_argv, RUN_USING_SHELL);
+
+	res = bisect_checkout(&current_rev, no_checkout);
+	if (res != BISECT_OK)
+		return -1;
+
+	return rc;
+}
+
 static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
 {
 	int res = BISECT_OK;
@@ -1096,6 +1134,7 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
 	struct strvec run_args = STRVEC_INIT;
 	const char *new_state;
 	int temporary_stdout_fd, saved_stdout;
+	int is_first_run = 1;

 	if (bisect_next_check(terms, NULL))
 		return BISECT_FAILED;
@@ -1113,6 +1152,30 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
 		printf(_("running %s\n"), command.buf);
 		res = run_command_v_opt(run_args.v, RUN_USING_SHELL);

+		/*
+		 * Exit code 126 and 127 can either come from the shell
+		 * if it was unable to execute or even find the script,
+		 * or from the script itself.  Check with a known-good
+		 * revision to avoid trashing the bisect run due to a
+		 * missing or non-executable script.
+		 */
+		if (is_first_run && (res == 126 || res == 127)) {
+			int rc = verify_good(terms, run_args.v);
+			is_first_run = 0;
+			if (rc < 0) {
+				error(_("unable to verify '%s' on good"
+					" revision"), command.buf);
+				res = BISECT_FAILED;
+				break;
+			}
+			if (rc == res) {
+				error(_("bogus exit code %d for good revision"),
+				      rc);
+				res = BISECT_FAILED;
+				break;
+			}
+		}
+
 		if (res < 0 || 128 <= res) {
 			error(_("bisect run failed: exit code %d from"
 				" '%s' is < 0 or >= 128"), res, command.buf);
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index fc18796517..5382e5d216 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -290,7 +290,7 @@ test_expect_success 'bisect run accepts exit code 126 as bad' '
 	grep "$HASH3 is the first bad commit" my_bisect_log.txt
 '

-test_expect_failure POSIXPERM 'bisect run fails with non-executable test script' '
+test_expect_success POSIXPERM 'bisect run fails with non-executable test script' '
 	test_when_finished "git bisect reset" &&
 	>not-executable.sh &&
 	chmod -x not-executable.sh &&
@@ -313,7 +313,7 @@ test_expect_success 'bisect run accepts exit code 127 as bad' '
 	grep "$HASH3 is the first bad commit" my_bisect_log.txt
 '

-test_expect_failure 'bisect run fails with missing test script' '
+test_expect_success 'bisect run fails with missing test script' '
 	test_when_finished "git bisect reset" &&
 	rm -f does-not-exist.sh &&
 	git bisect start &&
