diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index b4a0117330e..4e5490e734e 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -1569,6 +1569,13 @@ struct index_wip_file
   index_wip_file (const char *dir, const char *basename,
 		  const char *suffix)
   {
+    /* Validate DIR is a  valid directory.  */
+    struct stat buf;
+    if (stat (dir, &buf) == -1)
+      perror_with_name (string_printf (_("`%s'"), dir).c_str ());
+    if ((buf.st_mode & S_IFDIR) != S_IFDIR)
+      error (_("`%s': Is not a directory."), dir);
+
     filename = (std::string (dir) + SLASH_STRING + basename
 		+ suffix);
 
@@ -1577,7 +1584,8 @@ struct index_wip_file
     scoped_fd out_file_fd = gdb_mkostemp_cloexec (filename_temp.data (),
 						  O_BINARY);
     if (out_file_fd.get () == -1)
-      perror_with_name (("mkstemp"));
+      perror_with_name (string_printf (_("couldn't open `%s'"),
+				       filename_temp.data ()).c_str ());
 
     out_file = out_file_fd.to_file ("wb");
 
diff --git a/gdb/testsuite/gdb.base/gdb-index-err.c b/gdb/testsuite/gdb.base/gdb-index-err.c
new file mode 100644
index 00000000000..3a264f239ed
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gdb-index-err.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/gdb-index-err.exp b/gdb/testsuite/gdb.base/gdb-index-err.exp
new file mode 100644
index 00000000000..9493c3aafd2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gdb-index-err.exp
@@ -0,0 +1,118 @@
+# Copyright 2023 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test some error messages that can arise from the 'save gdb-index'
+# command.
+
+standard_testfile
+
+if {[build_executable "build executable" $testfile $srcfile] == -1} {
+    return -1
+}
+
+clean_restart $binfile
+
+# This test isn't going to work when the board file automatically adds
+# an index section, or if the debug information is split into a
+# separate objfile.
+set has_cooked_index false
+gdb_test_multiple "maint print objfiles ${binfile}" "check debug style" -lbl {
+    -re "\r\n\\.gdb_index: version ${decimal}(?=\r\n)" {
+	gdb_test_lines "" $gdb_test_name ".*"
+    }
+    -re "\r\n\\.debug_names: exists(?=\r\n)" {
+	gdb_test_lines "" $gdb_test_name ".*"
+    }
+    -re "\r\n(Cooked index in use:|Psymtabs)(?=\r\n)" {
+	set has_cooked_index true
+	gdb_test_lines "" $gdb_test_name ".*"
+    }
+    -re ".gdb_index: faked for \"readnow\"" {
+	gdb_test_lines "" $gdb_test_name ".*"
+    }
+    -re -wrap "" {
+	# Have no debug information!
+    }
+}
+
+if { !$has_cooked_index } {
+    unsupported "cannot test without a cooked index"
+    return -1
+}
+
+
+# The name of a directory that doesn't exist.
+set bad_dir [standard_output_file "non-existent"]
+
+# Try to write the index into a non-existent directory.
+foreach_with_prefix flag { "" "-dwarf-5" } {
+    gdb_test "save gdb-index ${flag} ${bad_dir}" \
+	"Error while writing index for `[string_to_regexp $binfile]': `[string_to_regexp $bad_dir]': No such file or directory\\." \
+	"try to write index to non-existent directory"
+}
+
+# Create a text-file.
+set text_file [standard_output_file "text-file"]
+set fd [open $text_file w]
+puts $fd "A line of text.\n"
+close $fd
+
+# Try to write the index into something that is not a directory.
+foreach_with_prefix flag { "" "-dwarf-5" } {
+    gdb_test "save gdb-index ${flag} ${text_file}" \
+	"Error while writing index for `[string_to_regexp $binfile]': `[string_to_regexp $text_file]': Is not a directory\\." \
+	"try to write index to something that's not a directory"
+}
+
+# Create a directory which can't be written too.
+set non_writable_dir [standard_output_file "private"]
+remote_exec host "mkdir -p ${non_writable_dir}"
+remote_exec host "chmod u-w,g-w ${non_writable_dir}"
+
+# Try to write the index into a non-writable directory.
+foreach_with_prefix flag { "" "-dwarf-5" } {
+    gdb_test "save gdb-index ${flag} ${non_writable_dir}" \
+	"Error while writing index for `[string_to_regexp $binfile]': couldn't open `[string_to_regexp $non_writable_dir]/${gdb_test_file_name}.*': Permission denied\\." \
+	"try to write index to a non-writable directory"
+}
+
+# Create copies of the executable, we will add an index section to
+# each of these.
+remote_exec host "cp $binfile ${binfile}.gdb_index"
+remote_exec host "cp $binfile ${binfile}.dwarf_5"
+
+# Create a directory in which we can try to generate the index files.
+set already_indexed_dir [standard_output_file "already_indexed"]
+remote_exec host "mkdir -p $already_indexed_dir"
+
+foreach_with_prefix flag { "" "-dwarf-5" } {
+    if { $flag eq "" } {
+	set extension "gdb_index"
+    } else {
+	set extension "dwarf_5"
+    }
+
+    # Add the index section to the executable.
+    clean_restart ${binfile}.${extension}
+    gdb_assert {[ensure_gdb_index ${binfile}.${extension} ${flag}] == 1} \
+	"add index to executable"
+
+    # Reload the executable (which now has an index), and try to
+    # generate and index from it.  This will fail.
+    clean_restart ${binfile}.${extension}
+    gdb_test "save gdb-index ${flag} $already_indexed_dir" \
+	"Error while writing index for `[string_to_regexp $binfile.$extension]': Cannot use an index to create the index" \
+	"try to generate an index from a binary with an index"
+}
