diff --git a/src/decoder/plugins/FluidsynthDecoderPlugin.cxx b/src/decoder/plugins/FluidsynthDecoderPlugin.cxx
index fb748e536..b2e2bf7f1 100644
--- a/src/decoder/plugins/FluidsynthDecoderPlugin.cxx
+++ b/src/decoder/plugins/FluidsynthDecoderPlugin.cxx
@@ -4,6 +4,7 @@
 #include "FluidsynthDecoderPlugin.hxx"
 #include "../DecoderAPI.hxx"
 #include "pcm/CheckAudioFormat.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "lib/fmt/RuntimeError.hxx"
 #include "util/Domain.hxx"
@@ -101,6 +102,8 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
 	fluid_player_t *player;
 	int ret;
 
+	auto np = NarrowPath(path_fs);
+
 	/* set up fluid settings */
 
 	settings = new_fluid_settings();
@@ -141,7 +144,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
 		return;
 	}
 
-	ret = fluid_player_add(player, path_fs.c_str());
+	ret = fluid_player_add(player, np);
 	if (ret != 0) {
 		LogWarning(fluidsynth_domain, "fluid_player_add() failed");
 		delete_fluid_player(player);
@@ -200,7 +203,8 @@ static bool
 fluidsynth_scan_file(Path path_fs,
 		     [[maybe_unused]] TagHandler &handler) noexcept
 {
-	return fluid_is_midifile(path_fs.c_str());
+	auto np = NarrowPath(path_fs);
+	return fluid_is_midifile(np);
 }
 
 static const char *const fluidsynth_suffixes[] = {
diff --git a/src/decoder/plugins/MikmodDecoderPlugin.cxx b/src/decoder/plugins/MikmodDecoderPlugin.cxx
index f4b7b4d30..19dc98949 100644
--- a/src/decoder/plugins/MikmodDecoderPlugin.cxx
+++ b/src/decoder/plugins/MikmodDecoderPlugin.cxx
@@ -7,6 +7,7 @@
 #include "lib/fmt/PathFormatter.hxx"
 #include "lib/fmt/RuntimeError.hxx"
 #include "tag/Handler.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "util/Domain.hxx"
 #include "Log.hxx"
@@ -128,9 +129,10 @@ mikmod_decoder_finish() noexcept
 static void
 mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
 {
+	auto np = NarrowPath(path_fs);
 	/* deconstify the path because libmikmod wants a non-const
 	   string pointer */
-	char *const path2 = const_cast<char *>(path_fs.c_str());
+	const auto path2 = const_cast<char *>(np.c_str());
 
 	MODULE *handle;
 	int ret;
@@ -167,9 +169,10 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
 static bool
 mikmod_decoder_scan_file(Path path_fs, TagHandler &handler) noexcept
 {
+	auto np = NarrowPath(path_fs);
 	/* deconstify the path because libmikmod wants a non-const
 	   string pointer */
-	char *const path2 = const_cast<char *>(path_fs.c_str());
+	const auto path2 = const_cast<char *>(np.c_str());
 
 	MODULE *handle = Player_Load(path2, 128, 0);
 
diff --git a/src/decoder/plugins/Mpg123DecoderPlugin.cxx b/src/decoder/plugins/Mpg123DecoderPlugin.cxx
index 54076b972..7e80ce734 100644
--- a/src/decoder/plugins/Mpg123DecoderPlugin.cxx
+++ b/src/decoder/plugins/Mpg123DecoderPlugin.cxx
@@ -8,6 +8,7 @@
 #include "tag/Builder.hxx"
 #include "tag/ReplayGainParser.hxx"
 #include "tag/MixRampParser.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "util/Domain.hxx"
 #include "util/ScopeExit.hxx"
@@ -43,14 +44,15 @@ mpd_mpg123_finish() noexcept
  * @return true on success
  */
 static bool
-mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
+mpd_mpg123_open(mpg123_handle *handle, Path path_fs,
 		AudioFormat &audio_format)
 {
-	int error = mpg123_open(handle, path_fs);
+	auto np = NarrowPath(path_fs);
+	int error = mpg123_open(handle, np);
 	if (error != MPG123_OK) {
 		FmtWarning(mpg123_domain,
 			   "libmpg123 failed to open {}: {}",
-			   path_fs, mpg123_plain_strerror(error));
+			   np.c_str(), mpg123_plain_strerror(error));
 		return false;
 	}
 
@@ -179,7 +181,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
 	AtScopeExit(handle) { mpg123_delete(handle); };
 
 	AudioFormat audio_format;
-	if (!mpd_mpg123_open(handle, path_fs.c_str(), audio_format))
+	if (!mpd_mpg123_open(handle, path_fs, audio_format))
 		return;
 
 	const off_t num_samples = mpg123_length(handle);
@@ -271,7 +273,7 @@ mpd_mpg123_scan_file(Path path_fs, TagHandler &handler) noexcept
 
 	AudioFormat audio_format;
 	try {
-		if (!mpd_mpg123_open(handle, path_fs.c_str(), audio_format)) {
+		if (!mpd_mpg123_open(handle, path_fs, audio_format)) {
 			return false;
 		}
 	} catch (...) {
diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx
index 6c671e490..6e21735b9 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.cxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx
@@ -7,6 +7,7 @@
 #include "tag/Handler.hxx"
 #include "tag/Builder.hxx"
 #include "song/DetachedSong.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "fs/AllocatedPath.hxx"
 #include "lib/fmt/PathFormatter.hxx"
@@ -155,10 +156,9 @@ ParseSubtuneName(const char *base) noexcept
 static SidplayContainerPath
 ParseContainerPath(Path path_fs) noexcept
 {
-	const Path base = path_fs.GetBase();
+	const NarrowPath base = NarrowPath(path_fs.GetBase());
 	unsigned track;
-	if (base.IsNull() ||
-	    (track = ParseSubtuneName(base.c_str())) < 1)
+	if (!base || (track = ParseSubtuneName(base)) < 1)
 		return { AllocatedPath(path_fs), 1 };
 
 	return { path_fs.GetDirectoryName(), track };
@@ -205,7 +205,8 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
 	/* load the tune */
 
 	const auto container = ParseContainerPath(path_fs);
-	SidTune tune(container.path.c_str());
+	auto np = NarrowPath(container.path);
+	auto tune = SidTune(np);
 	if (!tune.getStatus()) {
 		const char *error = tune.statusString();
 		FmtWarning(sidplay_domain, "failed to load file: {}", error);
@@ -435,7 +436,8 @@ sidplay_scan_file(Path path_fs, TagHandler &handler) noexcept
 	const auto container = ParseContainerPath(path_fs);
 	const unsigned song_num = container.track;
 
-	SidTune tune(container.path.c_str());
+	auto np = NarrowPath(container.path);
+	auto tune = SidTune(np);
 	if (!tune.getStatus())
 		return false;
 
@@ -459,7 +461,7 @@ sidplay_container_scan(Path path_fs)
 {
 	std::forward_list<DetachedSong> list;
 
-	SidTune tune(path_fs.c_str());
+	auto tune = SidTune{NarrowPath(path_fs)};
 	if (!tune.getStatus())
 		return list;
 
diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx
index 476a0e508..707333a8a 100644
--- a/src/decoder/plugins/WavpackDecoderPlugin.cxx
+++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx
@@ -7,6 +7,7 @@
 #include "input/InputStream.hxx"
 #include "pcm/CheckAudioFormat.hxx"
 #include "tag/Handler.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "lib/fmt/PathFormatter.hxx"
 #include "lib/fmt/RuntimeError.hxx"
@@ -36,8 +37,9 @@ static WavpackContext *
 WavpackOpenInput(Path path, int flags, int norm_offset)
 {
 	char error[ERRORLEN];
-	auto *wpc = WavpackOpenFileInput(path.c_str(), error,
-					 flags, norm_offset);
+	auto np = NarrowPath(path);
+	auto wpc = WavpackOpenFileInput(np, error,
+					flags, norm_offset);
 	if (wpc == nullptr)
 		throw FmtRuntimeError("failed to open WavPack file \"{}\": {}",
 				      path, error);
diff --git a/test/RunChromaprint.cxx b/test/RunChromaprint.cxx
index 54188b2d5..03d5a8c5d 100644
--- a/test/RunChromaprint.cxx
+++ b/test/RunChromaprint.cxx
@@ -10,6 +10,7 @@
 #include "decoder/DecoderAPI.hxx" /* for class StopDecoder */
 #include "input/Init.hxx"
 #include "input/InputStream.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "pcm/AudioFormat.hxx"
 #include "cmdline/OptionDef.hxx"
@@ -29,7 +30,7 @@ struct CommandLine {
 	const char *decoder = nullptr;
 	const char *uri = nullptr;
 
-	Path config_path = nullptr;
+	FromNarrowPath config_path = nullptr;
 
 	bool verbose = false;
 };
@@ -53,7 +54,7 @@ ParseCommandLine(int argc, char **argv)
 	while (auto o = option_parser.Next()) {
 		switch (Option(o.index)) {
 		case OPTION_CONFIG:
-			c.config_path = Path::FromFS(o.value);
+			c.config_path = o.value;
 			break;
 
 		case OPTION_VERBOSE:
@@ -112,7 +113,7 @@ try {
 	MyChromaprintDecoderClient client;
 	if (plugin->file_decode != nullptr) {
 		try {
-			plugin->FileDecode(client, Path::FromFS(c.uri));
+			plugin->FileDecode(client, FromNarrowPath(c.uri));
 		} catch (StopDecoder) {
 		}
 	} else if (plugin->stream_decode != nullptr) {
diff --git a/test/visit_archive.cxx b/test/visit_archive.cxx
index d2abe8dda..e4167a882 100644
--- a/test/visit_archive.cxx
+++ b/test/visit_archive.cxx
@@ -10,6 +10,7 @@
 #include "archive/ArchivePlugin.hxx"
 #include "archive/ArchiveFile.hxx"
 #include "archive/ArchiveVisitor.hxx"
+#include "fs/NarrowPath.hxx"
 #include "fs/Path.hxx"
 #include "util/PrintException.hxx"
 
@@ -54,7 +55,7 @@ try {
 	}
 
 	const char *plugin_name = argv[1];
-	const Path path = Path::FromFS(argv[2]);
+	const Path path = FromNarrowPath(argv[2]);
 
 	/* initialize MPD */