diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index 64b90e2e9..41a3fbba7 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -36,7 +36,7 @@
 #include "config/ConfigError.hxx"
 #include "config/ConfigGlobal.hxx"
 #include "config/Block.hxx"
-#include "util/Error.hxx"
+#include "util/RuntimeError.hxx"
 #include "Log.hxx"
 
 #include <stdexcept>
@@ -62,7 +62,7 @@ AudioOutput::AudioOutput(const AudioOutputPlugin &_plugin,
 }
 
 static const AudioOutputPlugin *
-audio_output_detect(Error &error)
+audio_output_detect()
 {
 	LogDefault(output_domain, "Attempt to detect audio output device");
 
@@ -77,8 +77,7 @@ audio_output_detect(Error &error)
 			return plugin;
 	}
 
-	error.Set(output_domain, "Unable to detect an audio device");
-	return nullptr;
+	throw std::runtime_error("Unable to detect an audio device");
 }
 
 /**
@@ -272,8 +271,7 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
 AudioOutput *
 audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
 		 MixerListener &mixer_listener,
-		 PlayerControl &pc,
-		 Error &error)
+		 PlayerControl &pc)
 {
 	const AudioOutputPlugin *plugin;
 
@@ -281,34 +279,25 @@ audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
 		const char *p;
 
 		p = block.GetBlockValue(AUDIO_OUTPUT_TYPE);
-		if (p == nullptr) {
-			error.Set(config_domain,
-				  "Missing \"type\" configuration");
-			return nullptr;
-		}
+		if (p == nullptr)
+			throw std::runtime_error("Missing \"type\" configuration");
 
 		plugin = AudioOutputPlugin_get(p);
-		if (plugin == nullptr) {
-			error.Format(config_domain,
-				     "No such audio output plugin: %s", p);
-			return nullptr;
-		}
+		if (plugin == nullptr)
+			throw FormatRuntimeError("No such audio output plugin: %s", p);
 	} else {
 		LogWarning(output_domain,
 			   "No 'AudioOutput' defined in config file");
 
-		plugin = audio_output_detect(error);
-		if (plugin == nullptr)
-			return nullptr;
+		plugin = audio_output_detect();
 
 		FormatDefault(output_domain,
 			      "Successfully detected a %s audio device",
 			      plugin->name);
 	}
 
-	AudioOutput *ao = ao_plugin_init(plugin, block, error);
-	if (ao == nullptr)
-		return nullptr;
+	AudioOutput *ao = ao_plugin_init(plugin, block);
+	assert(ao != nullptr);
 
 	try {
 		audio_output_setup(event_loop, *ao, mixer_listener, block);
diff --git a/src/output/Internal.hxx b/src/output/Internal.hxx
index 90d3f4d1a..750e58e97 100644
--- a/src/output/Internal.hxx
+++ b/src/output/Internal.hxx
@@ -30,7 +30,6 @@
 #include "thread/Thread.hxx"
 #include "system/PeriodClock.hxx"
 
-class Error;
 class PreparedFilter;
 class Filter;
 class MusicPipe;
@@ -467,8 +466,7 @@ extern struct notify audio_output_client_notify;
 AudioOutput *
 audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
 		 MixerListener &mixer_listener,
-		 PlayerControl &pc,
-		 Error &error);
+		 PlayerControl &pc);
 
 void
 audio_output_free(AudioOutput *ao);
diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index 0d4e7c61e..b5a6a49a7 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -26,7 +26,6 @@
 #include "MusicPipe.hxx"
 #include "MusicChunk.hxx"
 #include "system/FatalError.hxx"
-#include "util/Error.hxx"
 #include "config/Block.hxx"
 #include "config/ConfigGlobal.hxx"
 #include "config/ConfigOption.hxx"
@@ -54,14 +53,9 @@ static AudioOutput *
 LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener,
 	   PlayerControl &pc, const ConfigBlock &block)
 try {
-	Error error;
-	AudioOutput *output = audio_output_new(event_loop, block,
-					       mixer_listener,
-					       pc, error);
-	if (output == nullptr)
-		throw std::runtime_error(error.GetMessage());
-
-	return output;
+	return audio_output_new(event_loop, block,
+				mixer_listener,
+				pc);
 } catch (const std::runtime_error &e) {
 	if (block.line > 0)
 		FormatFatalError("line %i: %s",
diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx
index 538c86e1b..c2f8c7383 100644
--- a/src/output/MultipleOutputs.hxx
+++ b/src/output/MultipleOutputs.hxx
@@ -42,7 +42,6 @@ class MixerListener;
 struct MusicChunk;
 struct PlayerControl;
 struct AudioOutput;
-class Error;
 
 class MultipleOutputs {
 	MixerListener &mixer_listener;
diff --git a/src/output/OutputControl.cxx b/src/output/OutputControl.cxx
index 4b90333f8..15125e2cc 100644
--- a/src/output/OutputControl.cxx
+++ b/src/output/OutputControl.cxx
@@ -24,7 +24,6 @@
 #include "mixer/MixerControl.hxx"
 #include "notify.hxx"
 #include "filter/plugins/ReplayGainFilterPlugin.hxx"
-#include "util/Error.hxx"
 #include "Log.hxx"
 
 #include <stdexcept>
diff --git a/src/output/OutputPlugin.cxx b/src/output/OutputPlugin.cxx
index 7e99a6590..e90ba12a0 100644
--- a/src/output/OutputPlugin.cxx
+++ b/src/output/OutputPlugin.cxx
@@ -23,13 +23,12 @@
 
 AudioOutput *
 ao_plugin_init(const AudioOutputPlugin *plugin,
-	       const ConfigBlock &block,
-	       Error &error)
+	       const ConfigBlock &block)
 {
 	assert(plugin != nullptr);
 	assert(plugin->init != nullptr);
 
-	return plugin->init(block, error);
+	return plugin->init(block);
 }
 
 void
@@ -38,12 +37,11 @@ ao_plugin_finish(AudioOutput *ao)
 	ao->plugin.finish(ao);
 }
 
-bool
-ao_plugin_enable(AudioOutput *ao, Error &error_r)
+void
+ao_plugin_enable(AudioOutput *ao)
 {
-	return ao->plugin.enable != nullptr
-		? ao->plugin.enable(ao, error_r)
-		: true;
+	if (ao->plugin.enable != nullptr)
+		ao->plugin.enable(ao);
 }
 
 void
@@ -53,11 +51,10 @@ ao_plugin_disable(AudioOutput *ao)
 		ao->plugin.disable(ao);
 }
 
-bool
-ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format,
-	       Error &error)
+void
+ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format)
 {
-	return ao->plugin.open(ao, audio_format, error);
+	ao->plugin.open(ao, audio_format);
 }
 
 void
@@ -82,10 +79,9 @@ ao_plugin_send_tag(AudioOutput *ao, const Tag &tag)
 }
 
 size_t
-ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size,
-	       Error &error)
+ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size)
 {
-	return ao->plugin.play(ao, chunk, size, error);
+	return ao->plugin.play(ao, chunk, size);
 }
 
 void
diff --git a/src/output/OutputPlugin.hxx b/src/output/OutputPlugin.hxx
index 5f642cce0..a079be366 100644
--- a/src/output/OutputPlugin.hxx
+++ b/src/output/OutputPlugin.hxx
@@ -29,7 +29,6 @@ struct AudioFormat;
 struct Tag;
 struct AudioOutput;
 struct MixerPlugin;
-class Error;
 
 /**
  * A plugin which controls an audio output device.
@@ -54,10 +53,8 @@ struct AudioOutputPlugin {
 	 *
 	 * @param param the configuration section, or nullptr if there is
 	 * no configuration
-	 * @return nullptr on error, or an opaque pointer to the plugin's
-	 * data
 	 */
-	AudioOutput *(*init)(const ConfigBlock &block, Error &error);
+	AudioOutput *(*init)(const ConfigBlock &block);
 
 	/**
 	 * Free resources allocated by this device.
@@ -69,10 +66,8 @@ struct AudioOutputPlugin {
 	 * for the device to be opened.
 	 *
 	 * Throws #std::runtime_error on error.
-	 *
-	 * @return true on success, false on error
 	 */
-	bool (*enable)(AudioOutput *data, Error &error);
+	void (*enable)(AudioOutput *data);
 
 	/**
 	 * Disables the device.  It is closed before this method is
@@ -88,8 +83,7 @@ struct AudioOutputPlugin {
 	 * @param audio_format the audio format in which data is going
 	 * to be delivered; may be modified by the plugin
 	 */
-	bool (*open)(AudioOutput *data, AudioFormat &audio_format,
-		     Error &error);
+	void (*open)(AudioOutput *data, AudioFormat &audio_format);
 
 	/**
 	 * Close the device.
@@ -118,11 +112,10 @@ struct AudioOutputPlugin {
 	 *
 	 * Throws #std::runtime_error on error.
 	 *
-	 * @return the number of bytes played, or 0 on error
+	 * @return the number of bytes played
 	 */
 	size_t (*play)(AudioOutput *data,
-		       const void *chunk, size_t size,
-		       Error &error);
+		       const void *chunk, size_t size);
 
 	/**
 	 * Wait until the device has finished playing.
@@ -168,21 +161,19 @@ ao_plugin_test_default_device(const AudioOutputPlugin *plugin)
 gcc_malloc
 AudioOutput *
 ao_plugin_init(const AudioOutputPlugin *plugin,
-	       const ConfigBlock &block,
-	       Error &error);
+	       const ConfigBlock &block);
 
 void
 ao_plugin_finish(AudioOutput *ao);
 
-bool
-ao_plugin_enable(AudioOutput *ao, Error &error);
+void
+ao_plugin_enable(AudioOutput *ao);
 
 void
 ao_plugin_disable(AudioOutput *ao);
 
-bool
-ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format,
-	       Error &error);
+void
+ao_plugin_open(AudioOutput *ao, AudioFormat &audio_format);
 
 void
 ao_plugin_close(AudioOutput *ao);
@@ -195,8 +186,7 @@ void
 ao_plugin_send_tag(AudioOutput *ao, const Tag &tag);
 
 size_t
-ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size,
-	       Error &error);
+ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size);
 
 void
 ao_plugin_drain(AudioOutput *ao);
diff --git a/src/output/OutputThread.cxx b/src/output/OutputThread.cxx
index 62db4a233..53bdc3490 100644
--- a/src/output/OutputThread.cxx
+++ b/src/output/OutputThread.cxx
@@ -34,7 +34,6 @@
 #include "thread/Util.hxx"
 #include "thread/Slack.hxx"
 #include "thread/Name.hxx"
-#include "util/Error.hxx"
 #include "util/ConstBuffer.hxx"
 #include "Log.hxx"
 #include "Compiler.h"
@@ -62,13 +61,7 @@ AudioOutput::Enable()
 
 	try {
 		const ScopeUnlock unlock(mutex);
-		Error error;
-		if (!ao_plugin_enable(this, error)) {
-			FormatError(error,
-				    "Failed to enable \"%s\" [%s]",
-				    name, plugin.name);
-			return false;
-		}
+		ao_plugin_enable(this);
 	} catch (const std::runtime_error &e) {
 		FormatError(e,
 			    "Failed to enable \"%s\" [%s]",
@@ -138,8 +131,6 @@ AudioOutput::CloseFilter()
 inline void
 AudioOutput::Open()
 {
-	bool success;
-	Error error;
 	struct audio_format_string af_string;
 
 	assert(!open);
@@ -179,7 +170,7 @@ AudioOutput::Open()
 
  retry_without_dsd:
 	try {
-		success = ao_plugin_open(this, out_audio_format, error);
+		ao_plugin_open(this, out_audio_format);
 	} catch (const std::runtime_error &e) {
 		FormatError(e, "Failed to open \"%s\" [%s]",
 			    name, plugin.name);
@@ -194,19 +185,6 @@ AudioOutput::Open()
 
 	assert(!open);
 
-	if (!success) {
-		FormatError(error, "Failed to open \"%s\" [%s]",
-			    name, plugin.name);
-
-		{
-			const ScopeUnlock unlock(mutex);
-			CloseFilter();
-		}
-
-		fail_timer.Update();
-		return;
-	}
-
 	try {
 		convert_filter_set(convert_filter.Get(), out_audio_format);
 	} catch (const std::runtime_error &e) {
@@ -289,8 +267,6 @@ AudioOutput::CloseOutput(bool drain)
 void
 AudioOutput::ReopenFilter()
 {
-	Error error;
-
 	{
 		const ScopeUnlock unlock(mutex);
 		CloseFilter();
@@ -486,8 +462,6 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
 		return false;
 	}
 
-	Error error;
-
 	while (!data.IsEmpty() && command == Command::NONE) {
 		if (!WaitForDelay())
 			break;
@@ -496,13 +470,7 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
 
 		try {
 			const ScopeUnlock unlock(mutex);
-			nbytes = ao_plugin_play(this, data.data, data.size,
-						error);
-
-			if (nbytes == 0)
-				/* play()==0 means failure */
-				FormatError(error, "\"%s\" [%s] failed to play",
-					    name, plugin.name);
+			nbytes = ao_plugin_play(this, data.data, data.size);
 		} catch (const std::runtime_error &e) {
 			FormatError(e, "\"%s\" [%s] failed to play",
 				    name, plugin.name);
diff --git a/src/output/Wrapper.hxx b/src/output/Wrapper.hxx
index 031af7cda..69e389762 100644
--- a/src/output/Wrapper.hxx
+++ b/src/output/Wrapper.hxx
@@ -30,11 +30,9 @@ struct AudioOutputWrapper {
 		return ContainerCast(ao, &T::base);
 	}
 
-	static AudioOutput *Init(const ConfigBlock &block, Error &error) {
-		T *t = T::Create(block, error);
-		return t != nullptr
-			? &t->base
-			: nullptr;
+	static AudioOutput *Init(const ConfigBlock &block) {
+		T *t = T::Create(block);
+		return &t->base;
 	}
 
 	static void Finish(AudioOutput *ao) {
@@ -42,9 +40,9 @@ struct AudioOutputWrapper {
 		delete t;
 	}
 
-	static bool Enable(AudioOutput *ao, Error &error) {
+	static void Enable(AudioOutput *ao) {
 		T &t = Cast(*ao);
-		return t.Enable(error);
+		t.Enable();
 	}
 
 	static void Disable(AudioOutput *ao) {
@@ -52,10 +50,9 @@ struct AudioOutputWrapper {
 		t.Disable();
 	}
 
-	static bool Open(AudioOutput *ao, AudioFormat &audio_format,
-			 Error &error) {
+	static void Open(AudioOutput *ao, AudioFormat &audio_format) {
 		T &t = Cast(*ao);
-		return t.Open(audio_format, error);
+		t.Open(audio_format);
 	}
 
 	static void Close(AudioOutput *ao) {
@@ -75,10 +72,9 @@ struct AudioOutputWrapper {
 		t.SendTag(tag);
 	}
 
-	static size_t Play(AudioOutput *ao, const void *chunk, size_t size,
-			   Error &error) {
+	static size_t Play(AudioOutput *ao, const void *chunk, size_t size) {
 		T &t = Cast(*ao);
-		return t.Play(chunk, size, error);
+		return t.Play(chunk, size);
 	}
 
 	static void Drain(AudioOutput *ao) {
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index 4f9454691..26a46ff53 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -133,15 +133,15 @@ struct AlsaOutput {
 		return device.empty() ? default_device : device.c_str();
 	}
 
-	static AlsaOutput *Create(const ConfigBlock &block, Error &error);
+	static AlsaOutput *Create(const ConfigBlock &block);
 
-	bool Enable(Error &error);
+	void Enable();
 	void Disable();
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Drain();
 	void Cancel();
 
@@ -195,16 +195,15 @@ AlsaOutput::AlsaOutput(const ConfigBlock &block)
 }
 
 inline AlsaOutput *
-AlsaOutput::Create(const ConfigBlock &block, Error &)
+AlsaOutput::Create(const ConfigBlock &block)
 {
 	return new AlsaOutput(block);
 }
 
-inline bool
-AlsaOutput::Enable(gcc_unused Error &error)
+inline void
+AlsaOutput::Enable()
 {
 	pcm_export.Construct();
-	return true;
 }
 
 inline void
@@ -719,8 +718,8 @@ AlsaOutput::SetupOrDop(AudioFormat &audio_format, PcmExport::Params &params)
 #endif
 }
 
-inline bool
-AlsaOutput::Open(AudioFormat &audio_format, gcc_unused Error &error)
+inline void
+AlsaOutput::Open(AudioFormat &audio_format)
 {
 	int err = snd_pcm_open(&pcm, GetDevice(),
 			       SND_PCM_STREAM_PLAYBACK, mode);
@@ -751,8 +750,6 @@ AlsaOutput::Open(AudioFormat &audio_format, gcc_unused Error &error)
 	out_frame_size = pcm_export->GetFrameSize(audio_format);
 
 	must_prepare = false;
-
-	return true;
 }
 
 inline int
@@ -832,7 +829,7 @@ AlsaOutput::Close()
 }
 
 inline size_t
-AlsaOutput::Play(const void *chunk, size_t size, gcc_unused Error &error)
+AlsaOutput::Play(const void *chunk, size_t size)
 {
 	assert(size > 0);
 	assert(size % in_frame_size == 0);
diff --git a/src/output/plugins/AoOutputPlugin.cxx b/src/output/plugins/AoOutputPlugin.cxx
index 9f127eec5..fae233051 100644
--- a/src/output/plugins/AoOutputPlugin.cxx
+++ b/src/output/plugins/AoOutputPlugin.cxx
@@ -121,7 +121,7 @@ AoOutput::AoOutput(const ConfigBlock &block)
 }
 
 static AudioOutput *
-ao_output_init(const ConfigBlock &block, gcc_unused Error &error)
+ao_output_init(const ConfigBlock &block)
 {
 	return &(new AoOutput(block))->base;
 }
@@ -148,9 +148,8 @@ ao_output_close(AudioOutput *ao)
 	ao_close(ad->device);
 }
 
-static bool
-ao_output_open(AudioOutput *ao, AudioFormat &audio_format,
-	       gcc_unused Error &error)
+static void
+ao_output_open(AudioOutput *ao, AudioFormat &audio_format)
 {
 	ao_sample_format format = OUR_AO_FORMAT_INITIALIZER;
 	AoOutput *ad = (AoOutput *)ao;
@@ -181,8 +180,6 @@ ao_output_open(AudioOutput *ao, AudioFormat &audio_format,
 
 	if (ad->device == nullptr)
 		throw MakeAoError();
-
-	return true;
 }
 
 /**
@@ -203,8 +200,7 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
 }
 
 static size_t
-ao_output_play(AudioOutput *ao, const void *chunk, size_t size,
-	       gcc_unused Error &error)
+ao_output_play(AudioOutput *ao, const void *chunk, size_t size)
 {
 	AoOutput *ad = (AoOutput *)ao;
 
diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx
index ba5775fe0..f9ee3e5ae 100644
--- a/src/output/plugins/FifoOutputPlugin.cxx
+++ b/src/output/plugins/FifoOutputPlugin.cxx
@@ -54,7 +54,7 @@ public:
 		CloseFifo();
 	}
 
-	static FifoOutput *Create(const ConfigBlock &block, Error &error);
+	static FifoOutput *Create(const ConfigBlock &block);
 
 	void Create();
 	void Check();
@@ -63,11 +63,11 @@ public:
 	void OpenFifo();
 	void CloseFifo();
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	unsigned Delay() const;
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 };
 
@@ -169,16 +169,15 @@ try {
 }
 
 inline FifoOutput *
-FifoOutput::Create(const ConfigBlock &block, Error &)
+FifoOutput::Create(const ConfigBlock &block)
 {
 	return new FifoOutput(block);
 }
 
-bool
-FifoOutput::Open(AudioFormat &audio_format, gcc_unused Error &error)
+void
+FifoOutput::Open(AudioFormat &audio_format)
 {
 	timer = new Timer(audio_format);
-	return true;
 }
 
 void
@@ -214,7 +213,7 @@ FifoOutput::Delay() const
 }
 
 inline size_t
-FifoOutput::Play(const void *chunk, size_t size, Error &)
+FifoOutput::Play(const void *chunk, size_t size)
 {
 	if (!timer->IsStarted())
 		timer->Start();
diff --git a/src/output/plugins/HaikuOutputPlugin.cxx b/src/output/plugins/HaikuOutputPlugin.cxx
index 5ba297b40..337a880d8 100644
--- a/src/output/plugins/HaikuOutputPlugin.cxx
+++ b/src/output/plugins/HaikuOutputPlugin.cxx
@@ -71,12 +71,12 @@ public:
 
 	~HaikuOutput();
 
-	static HaikuOutput *Create(const ConfigBlock &block, Error &error);
+	static HaikuOutput *Create(const ConfigBlock &block);
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 
 	size_t Delay();
@@ -119,7 +119,7 @@ haiku_test_default_device(void)
 }
 
 inline HaikuOutput *
-HaikuOutput::Create(const ConfigBlock &block, Error &)
+HaikuOutput::Create(const ConfigBlock &block)
 {
 	initialize_application();
 
@@ -184,8 +184,8 @@ HaikuOutput::FillBuffer(void* _buffer, size_t size,
 	}
 }
 
-inline bool
-HaikuOutput::Open(AudioFormat &audio_format, Error &)
+inline void
+HaikuOutput::Open(AudioFormat &audio_format)
 {
 	status_t err;
 	format = media_multi_audio_format::wildcard;
@@ -261,12 +261,10 @@ HaikuOutput::Open(AudioFormat &audio_format, Error &)
 	sound_player->SetVolume(1.0);
 	sound_player->Start();
 	sound_player->SetHasData(false);
-
-	return true;
 }
 
 inline size_t
-HaikuOutput::Play(const void *chunk, size_t size, gcc_unused Error &error)
+HaikuOutput::Play(const void *chunk, size_t size)
 {
 	BSoundPlayer* const soundPlayer = sound_player;
 	const uint8 *data = (const uint8 *)chunk;
diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx
index 4dee7d8d8..171bae2cc 100644
--- a/src/output/plugins/JackOutputPlugin.cxx
+++ b/src/output/plugins/JackOutputPlugin.cxx
@@ -99,10 +99,10 @@ struct JackOutput {
 		shutdown = true;
 	}
 
-	bool Enable(Error &error);
+	void Enable();
 	void Disable();
 
-	bool Open(AudioFormat &new_audio_format, Error &error);
+	void Open(AudioFormat &new_audio_format);
 
 	void Close() {
 		Stop();
@@ -134,7 +134,7 @@ struct JackOutput {
 			: 0;
 	}
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 
 	bool Pause();
 };
@@ -420,14 +420,13 @@ mpd_jack_test_default_device(void)
 	return true;
 }
 
-inline bool
-JackOutput::Enable(Error &)
+inline void
+JackOutput::Enable()
 {
 	for (unsigned i = 0; i < num_source_ports; ++i)
 		ringbuffer[i] = nullptr;
 
 	Connect();
-	return true;
 }
 
 inline void
@@ -445,7 +444,7 @@ JackOutput::Disable()
 }
 
 static AudioOutput *
-mpd_jack_init(const ConfigBlock &block, Error &)
+mpd_jack_init(const ConfigBlock &block)
 {
 	jack_set_error_function(mpd_jack_error);
 
@@ -580,8 +579,8 @@ JackOutput::Start()
 	}
 }
 
-inline bool
-JackOutput::Open(AudioFormat &new_audio_format, Error &)
+inline void
+JackOutput::Open(AudioFormat &new_audio_format)
 {
 	pause = false;
 
@@ -595,7 +594,6 @@ JackOutput::Open(AudioFormat &new_audio_format, Error &)
 	audio_format = new_audio_format;
 
 	Start();
-	return true;
 }
 
 inline size_t
@@ -640,7 +638,7 @@ JackOutput::WriteSamples(const float *src, size_t n_frames)
 }
 
 inline size_t
-JackOutput::Play(const void *chunk, size_t size, Error &)
+JackOutput::Play(const void *chunk, size_t size)
 {
 	pause = false;
 
diff --git a/src/output/plugins/NullOutputPlugin.cxx b/src/output/plugins/NullOutputPlugin.cxx
index 601fc1039..650910e68 100644
--- a/src/output/plugins/NullOutputPlugin.cxx
+++ b/src/output/plugins/NullOutputPlugin.cxx
@@ -37,13 +37,11 @@ public:
 		:base(null_output_plugin, block),
 		 sync(block.GetBlockValue("sync", true)) {}
 
-	static NullOutput *Create(const ConfigBlock &block, Error &error);
+	static NullOutput *Create(const ConfigBlock &block);
 
-	bool Open(AudioFormat &audio_format, gcc_unused Error &error) {
+	void Open(AudioFormat &audio_format) {
 		if (sync)
 			timer = new Timer(audio_format);
-
-		return true;
 	}
 
 	void Close() {
@@ -57,8 +55,7 @@ public:
 			: 0;
 	}
 
-	size_t Play(gcc_unused const void *chunk, size_t size,
-		    gcc_unused Error &error) {
+	size_t Play(gcc_unused const void *chunk, size_t size) {
 		if (sync) {
 			if (!timer->IsStarted())
 				timer->Start();
@@ -75,7 +72,7 @@ public:
 };
 
 inline NullOutput *
-NullOutput::Create(const ConfigBlock &block, Error &)
+NullOutput::Create(const ConfigBlock &block)
 {
 	return new NullOutput(block);
 }
diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx
index f03637631..aaf937d39 100644
--- a/src/output/plugins/OSXOutputPlugin.cxx
+++ b/src/output/plugins/OSXOutputPlugin.cxx
@@ -104,7 +104,7 @@ OSXOutput::OSXOutput(const ConfigBlock &block)
 }
 
 static AudioOutput *
-osx_output_init(const ConfigBlock &block, Error &)
+osx_output_init(const ConfigBlock &block)
 {
 	OSXOutput *oo = new OSXOutput(block);
 
@@ -512,8 +512,8 @@ osx_render(void *vdata,
  	return noErr;
 }
 
-static bool
-osx_output_enable(AudioOutput *ao, Error &)
+static void
+osx_output_enable(AudioOutput *ao)
 {
 	char errormsg[1024];
 	OSXOutput *oo = (OSXOutput *)ao;
@@ -546,8 +546,6 @@ osx_output_enable(AudioOutput *ao, Error &)
 	if (oo->hog_device) {
 		osx_output_hog_device(oo->dev_id, true);
 	}
-
-	return true;
 }
 
 static void
@@ -573,9 +571,8 @@ osx_output_close(AudioOutput *ao)
 	delete od->ring_buffer;
 }
 
-static bool
-osx_output_open(AudioOutput *ao, AudioFormat &audio_format,
-		Error &)
+static void
+osx_output_open(AudioOutput *ao, AudioFormat &audio_format)
 {
 	char errormsg[1024];
 	OSXOutput *od = (OSXOutput *)ao;
@@ -662,13 +659,10 @@ osx_output_open(AudioOutput *ao, AudioFormat &audio_format,
 		throw FormatRuntimeError("unable to start audio output: %s",
 					 errormsg);
 	}
-
-	return true;
 }
 
 static size_t
-osx_output_play(AudioOutput *ao, const void *chunk, size_t size,
-		gcc_unused Error &error)
+osx_output_play(AudioOutput *ao, const void *chunk, size_t size)
 {
 	OSXOutput *od = (OSXOutput *)ao;
 	return od->ring_buffer->push((uint8_t *)chunk, size);
diff --git a/src/output/plugins/OpenALOutputPlugin.cxx b/src/output/plugins/OpenALOutputPlugin.cxx
index d2d208e54..0db98a2cb 100644
--- a/src/output/plugins/OpenALOutputPlugin.cxx
+++ b/src/output/plugins/OpenALOutputPlugin.cxx
@@ -52,10 +52,9 @@ class OpenALOutput {
 
 	OpenALOutput(const ConfigBlock &block);
 
-	static OpenALOutput *Create(const ConfigBlock &block, Error &error);
-
-	bool Open(AudioFormat &audio_format, Error &error);
+	static OpenALOutput *Create(const ConfigBlock &block);
 
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	gcc_pure
@@ -68,7 +67,7 @@ class OpenALOutput {
 			: 50;
 	}
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 
 	void Cancel();
 
@@ -147,13 +146,13 @@ OpenALOutput::OpenALOutput(const ConfigBlock &block)
 }
 
 inline OpenALOutput *
-OpenALOutput::Create(const ConfigBlock &block, Error &)
+OpenALOutput::Create(const ConfigBlock &block)
 {
 	return new OpenALOutput(block);
 }
 
-inline bool
-OpenALOutput::Open(AudioFormat &audio_format, Error &)
+inline void
+OpenALOutput::Open(AudioFormat &audio_format)
 {
 	format = openal_audio_format(audio_format);
 
@@ -174,8 +173,6 @@ OpenALOutput::Open(AudioFormat &audio_format, Error &)
 
 	filled = 0;
 	frequency = audio_format.sample_rate;
-
-	return true;
 }
 
 inline void
@@ -189,7 +186,7 @@ OpenALOutput::Close()
 }
 
 inline size_t
-OpenALOutput::Play(const void *chunk, size_t size, gcc_unused Error &error)
+OpenALOutput::Play(const void *chunk, size_t size)
 {
 	if (alcGetCurrentContext() != context)
 		alcMakeContextCurrent(context);
diff --git a/src/output/plugins/OssOutputPlugin.cxx b/src/output/plugins/OssOutputPlugin.cxx
index bb45dbefb..14318568d 100644
--- a/src/output/plugins/OssOutputPlugin.cxx
+++ b/src/output/plugins/OssOutputPlugin.cxx
@@ -89,12 +89,11 @@ public:
 		:base(oss_output_plugin, block),
 		 fd(-1), device(_device) {}
 
-	static OssOutput *Create(const ConfigBlock &block, Error &error);
+	static OssOutput *Create(const ConfigBlock &block);
 
 #ifdef AFMT_S24_PACKED
-	bool Enable(gcc_unused Error &error) {
+	void Enable() {
 		pcm_export.Construct();
-		return true;
 	}
 
 	void Disable() {
@@ -102,13 +101,13 @@ public:
 	}
 #endif
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 
 	void Close() {
 		DoClose();
 	}
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 
 private:
@@ -227,7 +226,7 @@ oss_open_default()
 }
 
 inline OssOutput *
-OssOutput::Create(const ConfigBlock &block, gcc_unused Error &error)
+OssOutput::Create(const ConfigBlock &block)
 {
 	const char *device = block.GetBlockValue("device");
 	if (device != nullptr)
@@ -638,8 +637,8 @@ try {
 	throw;
 }
 
-inline bool
-OssOutput::Open(AudioFormat &_audio_format, Error &)
+inline void
+OssOutput::Open(AudioFormat &_audio_format)
 try {
 	fd = open_cloexec(device, O_WRONLY, 0);
 	if (fd < 0)
@@ -648,7 +647,6 @@ try {
 	Setup(_audio_format);
 
 	audio_format = _audio_format;
-	return true;
 } catch (...) {
 	DoClose();
 	throw;
@@ -664,7 +662,7 @@ OssOutput::Cancel()
 }
 
 inline size_t
-OssOutput::Play(const void *chunk, size_t size, Error &)
+OssOutput::Play(const void *chunk, size_t size)
 {
 	ssize_t ret;
 
diff --git a/src/output/plugins/PipeOutputPlugin.cxx b/src/output/plugins/PipeOutputPlugin.cxx
index 476e5ebb0..cdd91acdb 100644
--- a/src/output/plugins/PipeOutputPlugin.cxx
+++ b/src/output/plugins/PipeOutputPlugin.cxx
@@ -39,15 +39,15 @@ class PipeOutput {
 	PipeOutput(const ConfigBlock &block);
 
 public:
-	static PipeOutput *Create(const ConfigBlock &block, Error &error);
+	static PipeOutput *Create(const ConfigBlock &block);
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 
 	void Close() {
 		pclose(fh);
 	}
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 };
 
 PipeOutput::PipeOutput(const ConfigBlock &block)
@@ -59,23 +59,21 @@ PipeOutput::PipeOutput(const ConfigBlock &block)
 }
 
 inline PipeOutput *
-PipeOutput::Create(const ConfigBlock &block, Error &)
+PipeOutput::Create(const ConfigBlock &block)
 {
 	return new PipeOutput(block);
 }
 
-inline bool
-PipeOutput::Open(gcc_unused AudioFormat &audio_format, Error &)
+inline void
+PipeOutput::Open(gcc_unused AudioFormat &audio_format)
 {
 	fh = popen(cmd.c_str(), "w");
 	if (fh == nullptr)
 		throw FormatErrno("Error opening pipe \"%s\"", cmd.c_str());
-
-	return true;
 }
 
 inline size_t
-PipeOutput::Play(const void *chunk, size_t size, Error &)
+PipeOutput::Play(const void *chunk, size_t size)
 {
 	size_t nbytes = fwrite(chunk, 1, size, fh);
 	if (nbytes == 0)
diff --git a/src/output/plugins/PulseOutputPlugin.cxx b/src/output/plugins/PulseOutputPlugin.cxx
index 541ff1e11..f71e54a12 100644
--- a/src/output/plugins/PulseOutputPlugin.cxx
+++ b/src/output/plugins/PulseOutputPlugin.cxx
@@ -93,16 +93,16 @@ public:
 	gcc_const
 	static bool TestDefaultDevice();
 
-	static PulseOutput *Create(const ConfigBlock &block, Error &error);
+	static PulseOutput *Create(const ConfigBlock &block);
 
-	bool Enable(Error &error);
+	void Enable();
 	void Disable();
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	unsigned Delay();
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 	bool Pause();
 
@@ -415,13 +415,13 @@ PulseOutput::SetupContext()
 }
 
 PulseOutput *
-PulseOutput::Create(const ConfigBlock &block, gcc_unused Error &error)
+PulseOutput::Create(const ConfigBlock &block)
 {
 	return new PulseOutput(block);
 }
 
-inline bool
-PulseOutput::Enable(gcc_unused Error &error)
+inline void
+PulseOutput::Enable()
 {
 	assert(mainloop == nullptr);
 
@@ -454,8 +454,6 @@ PulseOutput::Enable(gcc_unused Error &error)
 	}
 
 	pa_threaded_mainloop_unlock(mainloop);
-
-	return true;
 }
 
 inline void
@@ -607,8 +605,8 @@ PulseOutput::SetupStream(const pa_sample_spec &ss)
 				     pulse_output_stream_write_cb, this);
 }
 
-inline bool
-PulseOutput::Open(AudioFormat &audio_format, gcc_unused Error &error)
+inline void
+PulseOutput::Open(AudioFormat &audio_format)
 {
 	assert(mainloop != nullptr);
 
@@ -676,8 +674,6 @@ PulseOutput::Open(AudioFormat &audio_format, gcc_unused Error &error)
 		throw MakePulseError(context,
 				     "pa_stream_connect_playback() has failed");
 	}
-
-	return true;
 }
 
 inline void
@@ -759,7 +755,7 @@ PulseOutput::Delay()
 }
 
 inline size_t
-PulseOutput::Play(const void *chunk, size_t size, gcc_unused Error &error)
+PulseOutput::Play(const void *chunk, size_t size)
 {
 	assert(mainloop != nullptr);
 	assert(stream != nullptr);
diff --git a/src/output/plugins/PulseOutputPlugin.hxx b/src/output/plugins/PulseOutputPlugin.hxx
index c80ff85e3..59e63ec2f 100644
--- a/src/output/plugins/PulseOutputPlugin.hxx
+++ b/src/output/plugins/PulseOutputPlugin.hxx
@@ -23,7 +23,6 @@
 class PulseOutput;
 class PulseMixer;
 struct pa_cvolume;
-class Error;
 
 extern const struct AudioOutputPlugin pulse_output_plugin;
 
diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx
index fe76d57a7..294674f2d 100644
--- a/src/output/plugins/RecorderOutputPlugin.cxx
+++ b/src/output/plugins/RecorderOutputPlugin.cxx
@@ -81,9 +81,9 @@ class RecorderOutput {
 		delete prepared_encoder;
 	}
 
-	static RecorderOutput *Create(const ConfigBlock &block, Error &error);
+	static RecorderOutput *Create(const ConfigBlock &block);
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	/**
@@ -93,7 +93,7 @@ class RecorderOutput {
 
 	void SendTag(const Tag &tag);
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 
 private:
 	gcc_pure
@@ -141,7 +141,7 @@ RecorderOutput::RecorderOutput(const ConfigBlock &block)
 }
 
 RecorderOutput *
-RecorderOutput::Create(const ConfigBlock &block, Error &)
+RecorderOutput::Create(const ConfigBlock &block)
 {
 	return new RecorderOutput(block);
 }
@@ -154,8 +154,8 @@ RecorderOutput::EncoderToFile()
 	EncoderToOutputStream(*file, *encoder);
 }
 
-inline bool
-RecorderOutput::Open(AudioFormat &audio_format, Error &)
+inline void
+RecorderOutput::Open(AudioFormat &audio_format)
 {
 	/* create the output file */
 
@@ -195,8 +195,6 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &)
 		   soon as we have received a tag */
 		delete encoder;
 	}
-
-	return true;
 }
 
 inline void
@@ -349,7 +347,7 @@ RecorderOutput::SendTag(const Tag &tag)
 }
 
 inline size_t
-RecorderOutput::Play(const void *chunk, size_t size, Error &)
+RecorderOutput::Play(const void *chunk, size_t size)
 {
 	if (file == nullptr) {
 		/* not currently encoding to a file; discard incoming
diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx
index 7801b8b81..cbfc9ffce 100644
--- a/src/output/plugins/RoarOutputPlugin.cxx
+++ b/src/output/plugins/RoarOutputPlugin.cxx
@@ -58,11 +58,11 @@ public:
 		return &base;
 	}
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	void SendTag(const Tag &tag);
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 
 	int GetVolume() const;
@@ -134,7 +134,7 @@ roar_output_set_volume(RoarOutput &roar, unsigned volume)
 }
 
 static AudioOutput *
-roar_init(const ConfigBlock &block, Error &)
+roar_init(const ConfigBlock &block)
 {
 	return *new RoarOutput(block);
 }
@@ -174,8 +174,8 @@ roar_use_audio_format(struct roar_audio_info *info,
 	}
 }
 
-inline bool
-RoarOutput::Open(AudioFormat &audio_format, Error &)
+inline void
+RoarOutput::Open(AudioFormat &audio_format)
 {
 	const ScopeLock protect(mutex);
 
@@ -196,7 +196,6 @@ RoarOutput::Open(AudioFormat &audio_format, Error &)
 
 	roar_vs_role(vss, role, &err);
 	alive = true;
-	return true;
 }
 
 inline void
@@ -241,7 +240,7 @@ RoarOutput::Cancel()
 }
 
 inline size_t
-RoarOutput::Play(const void *chunk, size_t size, Error &)
+RoarOutput::Play(const void *chunk, size_t size)
 {
 	if (vss == nullptr)
 		throw std::runtime_error("Connection is invalid");
diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx
index 0d62b7e43..2bad712ad 100644
--- a/src/output/plugins/ShoutOutputPlugin.cxx
+++ b/src/output/plugins/ShoutOutputPlugin.cxx
@@ -58,14 +58,14 @@ struct ShoutOutput final {
 	explicit ShoutOutput(const ConfigBlock &block);
 	~ShoutOutput();
 
-	static ShoutOutput *Create(const ConfigBlock &block, Error &error);
+	static ShoutOutput *Create(const ConfigBlock &block);
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	unsigned Delay() const;
 	void SendTag(const Tag &tag);
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 	bool Pause();
 };
@@ -246,7 +246,7 @@ ShoutOutput::~ShoutOutput()
 }
 
 ShoutOutput *
-ShoutOutput::Create(const ConfigBlock &block, Error &)
+ShoutOutput::Create(const ConfigBlock &block)
 {
 	if (shout_init_count == 0)
 		shout_init();
@@ -340,8 +340,8 @@ shout_connect(ShoutOutput *sd)
 	}
 }
 
-bool
-ShoutOutput::Open(AudioFormat &audio_format, Error &)
+void
+ShoutOutput::Open(AudioFormat &audio_format)
 {
 	shout_connect(this);
 
@@ -358,8 +358,6 @@ ShoutOutput::Open(AudioFormat &audio_format, Error &)
 		shout_close(shout_conn);
 		throw;
 	}
-
-	return true;
 }
 
 unsigned
@@ -373,7 +371,7 @@ ShoutOutput::Delay() const
 }
 
 size_t
-ShoutOutput::Play(const void *chunk, size_t size, Error &)
+ShoutOutput::Play(const void *chunk, size_t size)
 {
 	encoder->Write(chunk, size);
 	write_page(this);
diff --git a/src/output/plugins/SndioOutputPlugin.cxx b/src/output/plugins/SndioOutputPlugin.cxx
index cb615f4d0..8af2d223b 100644
--- a/src/output/plugins/SndioOutputPlugin.cxx
+++ b/src/output/plugins/SndioOutputPlugin.cxx
@@ -47,14 +47,12 @@ class SndioOutput {
 public:
 	SndioOutput(const ConfigBlock &block);
 
-	bool Configure(const ConfigBlock &block, Error &error);
+	static SndioOutput *Create(const ConfigBlock &block);
 
-	static SndioOutput *Create(const ConfigBlock &block, Error &error);
-
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 	unsigned Delay() const;
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 	void Cancel();
 };
 
@@ -67,7 +65,7 @@ SndioOutput::SndioOutput(const ConfigBlock &block)
 }
 
 SndioOutput *
-SndioOutput::Create(const ConfigBlock &block, Error &)
+SndioOutput::Create(const ConfigBlock &block)
 {
 	return new SndioOutput(block);
 }
@@ -88,8 +86,8 @@ sndio_test_default_device()
 	return true;
 }
 
-bool
-SndioOutput::Open(AudioFormat &audio_format, Error &)
+void
+SndioOutput::Open(AudioFormat &audio_format)
 {
 	struct sio_par par;
 	unsigned bits, rate, chans;
@@ -145,8 +143,6 @@ SndioOutput::Open(AudioFormat &audio_format, Error &)
 		sio_close(sio_hdl);
 		throw std::runtime_error("Failed to start audio device");
 	}
-
-	return true;
 }
 
 void
@@ -156,7 +152,7 @@ SndioOutput::Close()
 }
 
 size_t
-SndioOutput::Play(const void *chunk, size_t size, Error &)
+SndioOutput::Play(const void *chunk, size_t size)
 {
 	size_t n;
 
diff --git a/src/output/plugins/SolarisOutputPlugin.cxx b/src/output/plugins/SolarisOutputPlugin.cxx
index 4f7608ef4..650d0dc97 100644
--- a/src/output/plugins/SolarisOutputPlugin.cxx
+++ b/src/output/plugins/SolarisOutputPlugin.cxx
@@ -72,7 +72,7 @@ solaris_output_test_default_device(void)
 }
 
 static AudioOutput *
-solaris_output_init(const ConfigBlock &block, Error &)
+solaris_output_init(const ConfigBlock &block)
 {
 	SolarisOutput *so = new SolarisOutput(block);
 	return &so->base;
@@ -86,8 +86,8 @@ solaris_output_finish(AudioOutput *ao)
 	delete so;
 }
 
-static bool
-solaris_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &)
+static void
+solaris_output_open(AudioOutput *ao, AudioFormat &audio_format)
 {
 	SolarisOutput *so = (SolarisOutput *)ao;
 	struct audio_info info;
@@ -130,8 +130,6 @@ solaris_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &)
 		close(so->fd);
 		throw MakeErrno(e, "AUDIO_SETINFO failed");
 	}
-
-	return true;
 }
 
 static void
@@ -143,8 +141,7 @@ solaris_output_close(AudioOutput *ao)
 }
 
 static size_t
-solaris_output_play(AudioOutput *ao, const void *chunk, size_t size,
-		    Error &)
+solaris_output_play(AudioOutput *ao, const void *chunk, size_t size)
 {
 	SolarisOutput *so = (SolarisOutput *)ao;
 	ssize_t nbytes;
diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx
index a92286166..f5dac2452 100644
--- a/src/output/plugins/WinmmOutputPlugin.cxx
+++ b/src/output/plugins/WinmmOutputPlugin.cxx
@@ -63,14 +63,14 @@ public:
 		return handle;
 	}
 
-	static WinmmOutput *Create(const ConfigBlock &block, Error &) {
+	static WinmmOutput *Create(const ConfigBlock &block) {
 		return new WinmmOutput(block);
 	}
 
-	bool Open(AudioFormat &audio_format, Error &);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
-	size_t Play(const void *chunk, size_t size, Error &);
+	size_t Play(const void *chunk, size_t size);
 	void Drain();
 	void Cancel();
 
@@ -153,8 +153,8 @@ WinmmOutput::WinmmOutput(const ConfigBlock &block)
 {
 }
 
-bool
-WinmmOutput::Open(AudioFormat &audio_format, Error &)
+void
+WinmmOutput::Open(AudioFormat &audio_format)
 {
 	event = CreateEvent(nullptr, false, false, nullptr);
 	if (event == nullptr)
@@ -199,8 +199,6 @@ WinmmOutput::Open(AudioFormat &audio_format, Error &)
 		memset(&i.hdr, 0, sizeof(i.hdr));
 
 	next_buffer = 0;
-
-	return true;
 }
 
 void
@@ -260,7 +258,7 @@ WinmmOutput::DrainBuffer(WinmmBuffer &buffer)
 }
 
 size_t
-WinmmOutput::Play(const void *chunk, size_t size, Error &)
+WinmmOutput::Play(const void *chunk, size_t size)
 {
 	/* get the next buffer from the ring and prepare it */
 	WinmmBuffer *buffer = &buffers[next_buffer];
diff --git a/src/output/plugins/httpd/HttpdInternal.hxx b/src/output/plugins/httpd/HttpdInternal.hxx
index a402b4a81..864720917 100644
--- a/src/output/plugins/httpd/HttpdInternal.hxx
+++ b/src/output/plugins/httpd/HttpdInternal.hxx
@@ -178,7 +178,7 @@ public:
 	/**
 	 * Caller must lock the mutex.
 	 */
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 
 	/**
 	 * Caller must lock the mutex.
diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.cxx b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
index cf438e555..fdd4ba072 100644
--- a/src/output/plugins/httpd/HttpdOutputPlugin.cxx
+++ b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
@@ -118,7 +118,7 @@ HttpdOutput::Unbind()
 }
 
 static AudioOutput *
-httpd_output_init(const ConfigBlock &block, Error &)
+httpd_output_init(const ConfigBlock &block)
 {
 	return *new HttpdOutput(io_thread_get(), block);
 }
@@ -247,13 +247,12 @@ HttpdOutput::ReadPage()
 	return Page::Copy(buffer, size);
 }
 
-static bool
-httpd_output_enable(AudioOutput *ao, gcc_unused Error &error)
+static void
+httpd_output_enable(AudioOutput *ao)
 {
 	HttpdOutput *httpd = HttpdOutput::Cast(ao);
 
 	httpd->Bind();
-	return true;
 }
 
 static void
@@ -277,8 +276,8 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format)
 	unflushed_input = 0;
 }
 
-inline bool
-HttpdOutput::Open(AudioFormat &audio_format, Error &)
+inline void
+HttpdOutput::Open(AudioFormat &audio_format)
 {
 	assert(!open);
 	assert(clients.empty());
@@ -290,18 +289,15 @@ HttpdOutput::Open(AudioFormat &audio_format, Error &)
 	timer = new Timer(audio_format);
 
 	open = true;
-
-	return true;
 }
 
-static bool
-httpd_output_open(AudioOutput *ao, AudioFormat &audio_format,
-		  Error &error)
+static void
+httpd_output_open(AudioOutput *ao, AudioFormat &audio_format)
 {
 	HttpdOutput *httpd = HttpdOutput::Cast(ao);
 
 	const ScopeLock protect(httpd->mutex);
-	return httpd->Open(audio_format, error);
+	httpd->Open(audio_format);
 }
 
 inline void
@@ -431,8 +427,7 @@ HttpdOutput::Play(const void *chunk, size_t size)
 }
 
 static size_t
-httpd_output_play(AudioOutput *ao, const void *chunk, size_t size,
-		  Error &)
+httpd_output_play(AudioOutput *ao, const void *chunk, size_t size)
 {
 	HttpdOutput *httpd = HttpdOutput::Cast(ao);
 
diff --git a/src/output/plugins/sles/SlesOutputPlugin.cxx b/src/output/plugins/sles/SlesOutputPlugin.cxx
index 5003dbbbd..01264aaa6 100644
--- a/src/output/plugins/sles/SlesOutputPlugin.cxx
+++ b/src/output/plugins/sles/SlesOutputPlugin.cxx
@@ -91,16 +91,16 @@ public:
 		return &base;
 	}
 
-	static SlesOutput *Create(const ConfigBlock &block, Error &error);
+	static SlesOutput *Create(const ConfigBlock &block);
 
-	bool Open(AudioFormat &audio_format, Error &error);
+	void Open(AudioFormat &audio_format);
 	void Close();
 
 	unsigned Delay() {
 		return pause && !cancel ? 100 : 0;
 	}
 
-	size_t Play(const void *chunk, size_t size, Error &error);
+	size_t Play(const void *chunk, size_t size);
 
 	void Drain();
 	void Cancel();
@@ -129,8 +129,8 @@ SlesOutput::SlesOutput(const ConfigBlock &block)
 {
 }
 
-inline bool
-SlesOutput::Open(AudioFormat &audio_format, Error &)
+inline void
+SlesOutput::Open(AudioFormat &audio_format)
 {
 	SLresult result;
 	SLObjectItf _object;
@@ -146,7 +146,6 @@ SlesOutput::Open(AudioFormat &audio_format, Error &)
 	if (result != SL_RESULT_SUCCESS) {
 		engine_object.Destroy();
 		throw std::runtime_error("Engine.Realize() failed");
-		return false;
 	}
 
 	SLEngineItf _engine;
@@ -294,7 +293,6 @@ SlesOutput::Open(AudioFormat &audio_format, Error &)
 
 	// TODO: support other sample formats
 	audio_format.format = SampleFormat::S16;
-	return true;
 }
 
 inline void
@@ -307,7 +305,7 @@ SlesOutput::Close()
 }
 
 inline size_t
-SlesOutput::Play(const void *chunk, size_t size, Error &)
+SlesOutput::Play(const void *chunk, size_t size)
 {
 	cancel = false;
 
@@ -413,7 +411,7 @@ sles_test_default_device()
 }
 
 inline SlesOutput *
-SlesOutput::Create(const ConfigBlock &block, Error &)
+SlesOutput::Create(const ConfigBlock &block)
 {
 	return new SlesOutput(block);
 }
diff --git a/src/player/Control.cxx b/src/player/Control.cxx
index c61369c95..905165432 100644
--- a/src/player/Control.cxx
+++ b/src/player/Control.cxx
@@ -21,7 +21,6 @@
 #include "Control.hxx"
 #include "Idle.hxx"
 #include "DetachedSong.hxx"
-#include "util/Error.hxx"
 
 #include <algorithm>
 
@@ -171,15 +170,6 @@ PlayerControl::SetError(PlayerError type, std::exception_ptr &&_error)
 	error = std::move(_error);
 }
 
-void
-PlayerControl::SetError(PlayerError type, Error &&_error)
-{
-	assert(type != PlayerError::NONE);
-	assert(_error.IsDefined());
-
-	SetError(type, std::make_exception_ptr(std::move(_error)));
-}
-
 void
 PlayerControl::LockClearError()
 {
diff --git a/src/player/Control.hxx b/src/player/Control.hxx
index b0e985e91..4b56e88b6 100644
--- a/src/player/Control.hxx
+++ b/src/player/Control.hxx
@@ -355,9 +355,7 @@ public:
 	 * Caller must lock the object.
 	 *
 	 * @param type the error type; must not be #PlayerError::NONE
-	 * @param error detailed error information; must be defined.
 	 */
-	void SetError(PlayerError type, Error &&error);
 	void SetError(PlayerError type, std::exception_ptr &&_error);
 
 	/**
diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx
index 42f3d8d4e..8d45e2e2a 100644
--- a/src/player/Thread.cxx
+++ b/src/player/Thread.cxx
@@ -33,7 +33,6 @@
 #include "tag/Tag.hxx"
 #include "Idle.hxx"
 #include "util/Domain.hxx"
-#include "util/Error.hxx"
 #include "thread/Name.hxx"
 #include "Log.hxx"
 
diff --git a/test/run_output.cxx b/test/run_output.cxx
index f06466d16..360e70b76 100644
--- a/test/run_output.cxx
+++ b/test/run_output.cxx
@@ -32,7 +32,8 @@
 #include "pcm/PcmConvert.hxx"
 #include "filter/FilterRegistry.hxx"
 #include "player/Control.hxx"
-#include "util/Error.hxx"
+#include "util/RuntimeError.hxx"
+#include "util/ScopeExit.hxx"
 #include "Log.hxx"
 
 #include <assert.h>
@@ -62,43 +63,29 @@ load_audio_output(EventLoop &event_loop, const char *name)
 {
 	const auto *param = config_find_block(ConfigBlockOption::AUDIO_OUTPUT,
 					      "name", name);
-	if (param == NULL) {
-		fprintf(stderr, "No such configured audio output: %s\n", name);
-		return nullptr;
-	}
+	if (param == NULL)
+		throw FormatRuntimeError("No such configured audio output: %s\n",
+					 name);
 
 	static struct PlayerControl dummy_player_control(*(PlayerListener *)nullptr,
 							 *(MultipleOutputs *)nullptr,
 							 32, 4);
 
-	Error error;
-	AudioOutput *ao =
-		audio_output_new(event_loop, *param,
-				 *(MixerListener *)nullptr,
-				 dummy_player_control,
-				 error);
-	if (ao == nullptr)
-		LogError(error);
-
-	return ao;
+	return audio_output_new(event_loop, *param,
+				*(MixerListener *)nullptr,
+				dummy_player_control);
 }
 
-static bool
+static void
 run_output(AudioOutput *ao, AudioFormat audio_format)
 {
 	/* open the audio output */
 
-	Error error;
-	if (!ao_plugin_enable(ao, error)) {
-		LogError(error, "Failed to enable audio output");
-		return false;
-	}
+	ao_plugin_enable(ao);
+	AtScopeExit(ao) { ao_plugin_disable(ao); };
 
-	if (!ao_plugin_open(ao, audio_format, error)) {
-		ao_plugin_disable(ao);
-		LogError(error, "Failed to open audio output");
-		return false;
-	}
+	ao_plugin_open(ao, audio_format);
+	AtScopeExit(ao) { ao_plugin_close(ao); };
 
 	struct audio_format_string af_string;
 	fprintf(stderr, "audio_format=%s\n",
@@ -123,14 +110,7 @@ run_output(AudioOutput *ao, AudioFormat audio_format)
 		size_t play_length = (length / frame_size) * frame_size;
 		if (play_length > 0) {
 			size_t consumed = ao_plugin_play(ao,
-							 buffer, play_length,
-							 error);
-			if (consumed == 0) {
-				ao_plugin_close(ao);
-				ao_plugin_disable(ao);
-				LogError(error, "Failed to play");
-				return false;
-			}
+							 buffer, play_length);
 
 			assert(consumed <= length);
 			assert(consumed % frame_size == 0);
@@ -139,16 +119,10 @@ run_output(AudioOutput *ao, AudioFormat audio_format)
 			memmove(buffer, buffer + consumed, length);
 		}
 	}
-
-	ao_plugin_close(ao);
-	ao_plugin_disable(ao);
-	return true;
 }
 
 int main(int argc, char **argv)
 try {
-	Error error;
-
 	if (argc < 3 || argc > 4) {
 		fprintf(stderr, "Usage: run_output CONFIG NAME [FORMAT] <IN\n");
 		return EXIT_FAILURE;
@@ -170,8 +144,6 @@ try {
 	/* initialize the audio output */
 
 	AudioOutput *ao = load_audio_output(event_loop, argv[2]);
-	if (ao == NULL)
-		return 1;
 
 	/* parse the audio format */
 
@@ -180,7 +152,7 @@ try {
 
 	/* do it */
 
-	bool success = run_output(ao, audio_format);
+	run_output(ao, audio_format);
 
 	/* cleanup and exit */
 
@@ -188,7 +160,7 @@ try {
 
 	config_global_finish();
 
-	return success ? EXIT_SUCCESS : EXIT_FAILURE;
+	return EXIT_SUCCESS;
  } catch (const std::exception &e) {
 	LogError(e);
 	return EXIT_FAILURE;