diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index d3f5e5039484d90d2223c7b32fdf81a81bab004f..0db76ef4aa43b37703c42a4bdd19261fa3882d23 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -187,7 +187,7 @@ App.Data.defaultGameStateVariables = {
 	aiSamplingSteps: 20,
 	aiSamplingStepsEvent: 20,
 	aiStyle: 1,
-	aiRestoreFaces: true,
+	aiRestoreFaces: false,
 	aiUpscale: false,
 	aiUpscaleScale: 1.75,
 	aiUpscaler: "SwinIR_4x",
diff --git a/src/art/genAI/stableDiffusion.js b/src/art/genAI/stableDiffusion.js
index 18a810fcddeab258d910d1c6bb24845e4dc09d4c..e73f5f91b665e951a7a0faa7ad3676633ad13d83 100644
--- a/src/art/genAI/stableDiffusion.js
+++ b/src/art/genAI/stableDiffusion.js
@@ -292,6 +292,83 @@ App.Art.GenAI.StableDiffusionClient = class {
 		return settings;
 	}
 
+	/** Note the long timeout; if SD is actively rendering it'll sometimes stop responding to API queries.
+	 * Do not block on API calls.
+	 * @param {string} relativeUrl
+	 * @returns {Promise<Response>}
+	 */
+	async fetchAPIQuery(relativeUrl) {
+		return fetchWithTimeout(`${V.aiApiUrl}${relativeUrl}`, 30000, {method: "GET"});
+	}
+
+	/**
+	 * @returns {Promise<string[]>}
+	 */
+	async getUpscalerList() {
+		return this.fetchAPIQuery(`/sdapi/v1/upscalers`)
+			.then((value) => {
+				return value.json();
+			})
+			.then((list) => {
+				return list.map(o => o.name);
+			})
+			.catch(err => {
+				console.log(`Failed to get upscaler list from Stable Diffusion.`);
+				return [];
+			});
+	}
+
+	/**
+	 * @returns {Promise<string[]>}
+	 */
+	async getSamplerList() {
+		return this.fetchAPIQuery(`/sdapi/v1/samplers`)
+			.then((value) => {
+				return value.json();
+			})
+			.then((list) => {
+				return list.map(o => o.name);
+			})
+			.catch(err => {
+				console.log(`Failed to get sampler list from Stable Diffusion.`);
+				return [];
+			});
+	}
+
+	/** Check to see whether a face restore model is configured.
+	 * @returns {Promise<boolean>}
+	 */
+	async canRestoreFaces() {
+		return this.fetchAPIQuery(`/sdapi/v1/face-restorers`)
+			.then((value) => {
+				return value.json();
+			})
+			.then((list) => {
+				return list.some(o => !!o.cmd_dir);
+			})
+			.catch(err => {
+				console.log(`Failed to get face restorers from Stable Diffusion.`);
+				return false;
+			});
+	}
+
+	/** Check to see if the ADetailer script is installed. Probably should check more than that, but this'll catch the dumb cases.
+	 * @returns {Promise<boolean>}
+	 */
+	async hasAdetailer() {
+		return this.fetchAPIQuery(`/sdapi/v1/script-info`)
+			.then((value) => {
+				return value.json();
+			})
+			.then((list) => {
+				return list.some(o => o.name === "adetailer");
+			})
+			.catch(err => {
+				console.log(`Failed to get script information from Stable Diffusion.`);
+				return false;
+			});
+	}
+
 	/**
 	 * @param {FC.SlaveState} slave
 	 * @param {boolean | null} isEventImage - Whether request is canceled on passage change and which step setting to use. true => V.aiSamplingStepsEvent, false => V.aiSamplingSteps, null => chosen based on passage tags
diff --git a/src/gui/options/options.js b/src/gui/options/options.js
index 0e52f7032f9141a7943d67d1ad2d0f1a4d2c34a0..9066b3da51d3909a4e67d79f1e8d2615a3da403d 100644
--- a/src/gui/options/options.js
+++ b/src/gui/options/options.js
@@ -1290,6 +1290,9 @@ App.UI.artOptions = function() {
 			} else if (V.imageChoice === 6) {
 				options.addComment("This is highly experimental. Please follow the setup instructions below.");
 				options.addCustom(App.UI.stableDiffusionInstallationGuide("Stable Diffusion Installation Guide"));
+				if (V.aiApiUrl.endsWith('/')) { // common error is including a trailing slash, which will fuck us up, so strip it automatically
+					V.aiApiUrl = V.aiApiUrl.slice(0, -1);
+				}
 				options.addOption("API URL", "aiApiUrl").showTextBox().addComment("The URL of the Automatic 1111 Stable Diffusion API.");
 				App.UI.aiPromptingOptions(options);
 				options.addOption("Automatic generation", "aiAutoGen")
@@ -1303,8 +1306,23 @@ App.UI.artOptions = function() {
 					options.addOption("Regeneration Frequency", "aiAutoGenFrequency").showTextBox()
 						.addComment("How often (in weeks) regenerate slave images. Slaves will render when 'Weeks Owned' is divisible by this number.");
 				}
+
+				const samplerListSpan = App.UI.DOM.makeElement('span', `Fetching options, please wait...`);
+				App.Art.GenAI.client.getSamplerList().then(list => {
+					if (list.length === 0) {
+						samplerListSpan.textContent = `Could not fetch valid samplers. Check your configuration.`;
+						samplerListSpan.classList.add('error');
+					} else {
+						samplerListSpan.textContent = `Valid options on your Stable Diffusion installation: ${toSentence(list)}.`;
+						if (!list.includes(V.aiSamplingMethod)) {
+							samplerListSpan.classList.add('error');
+							samplerListSpan.textContent = "ERROR: " + samplerListSpan.textContent;
+						}
+					}
+				});
 				options.addOption("Sampling Method", "aiSamplingMethod").showTextBox()
-					.addComment(`The sampling method used by AI. You can query ${V.aiApiUrl}/sdapi/v1/samplers to see the list of available samplers.`);
+					.addComment(App.UI.DOM.combineNodes(`The sampling method used by AI. `, samplerListSpan));
+
 				if (V.aiCfgScale < 1) {
 					V.aiCfgScale = 1;
 				}
@@ -1335,20 +1353,60 @@ App.UI.artOptions = function() {
 				}
 				options.addOption("Width", "aiWidth").showTextBox()
 					.addComment("The width of the image.");
+
+				const rfCheckSpan = App.UI.DOM.makeElement('span', `Validating Restore Faces...`);
+				App.Art.GenAI.client.canRestoreFaces().then(result => {
+					if (result) {
+						if (V.aiAdetailerFace && V.aiRestoreFaces) {
+							rfCheckSpan.textContent = `Do not use Restore Faces and ADetailer Restore Face at the same time. Pick one.`;
+							rfCheckSpan.classList.add("error");
+						} else {
+							rfCheckSpan.textContent = "";
+						}
+					} else {
+						rfCheckSpan.textContent = `Restore Faces is unavailable on your Stable Diffusion installation.`;
+						rfCheckSpan.classList.add("error");
+					}
+				});
 				options.addOption("Restore Faces", "aiRestoreFaces")
 					.addValue("Enabled", true).on().addValue("Disabled", false).off()
-					.addComment("Use a model to restore the faces after the image has been generated.");
+					.addComment(App.UI.DOM.combineNodes("Use a model to restore faces after the image has been generated. May result in 'samey' faces. ", rfCheckSpan));
+
+				const adCheckSpan = App.UI.DOM.makeElement('span', `Validating ADetailer setup...`);
+				App.Art.GenAI.client.hasAdetailer().then(result => {
+					if (result) {
+						adCheckSpan.textContent = "";
+					} else {
+						adCheckSpan.textContent = `ADetailer is unavailable on your Stable Diffusion installation.`;
+						adCheckSpan.classList.add("error");
+					}
+				});
+				options.addOption("ADetailer restore face", "aiAdetailerFace")
+					.addValue("Enabled", true).on().addValue("Disabled", false).off()
+					.addComment(App.UI.DOM.combineNodes("Use AI to recognize and re-render faces with better detail. Much better than Restore Faces, but requires more technical setup. ", adCheckSpan));
+
 				options.addOption("Upscaling/highres fix", "aiUpscale")
 					.addValue("Enabled", true).on().addValue("Disabled", false).off()
 					.addComment("Use AI upscaling to produce higher-resolution images. Significantly increases both time to generate and image quality.");
-				options.addOption("ADetailer restore face", "aiAdetailerFace")
-					.addValue("Enabled", true).on().addValue("Disabled", false).off()
-					.addComment("Use AI to clean up the face. Extremely small impact to generation time, moderate impact to image quality. Allows you to use a higher CFG.");
 				if (V.aiUpscale) {
 					options.addOption("Upscaling size", "aiUpscaleScale").showTextBox()
-						.addComment("Scales the dimensions of the image by this factor. Defaults to 1.7.");
+						.addComment("Scales the dimensions of the image by this factor. Defaults to 1.75.");
+
+					const upscalerListSpan = App.UI.DOM.makeElement('span', `Fetching options, please wait...`);
+					App.Art.GenAI.client.getUpscalerList().then(list => {
+						if (list.length === 0) {
+							upscalerListSpan.textContent = `Could not fetch valid upscalers. Check your configuration.`;
+							upscalerListSpan.classList.add('error');
+						} else {
+							upscalerListSpan.textContent = `Valid options on your Stable Diffusion installation: ${toSentence(list)}.`;
+							if (!list.includes(V.aiUpscaler)) {
+								upscalerListSpan.classList.add('error');
+								upscalerListSpan.textContent = "ERROR: " + upscalerListSpan.textContent;
+							}
+						}
+					});
 					options.addOption("Upscaling method", "aiUpscaler").showTextBox()
-						.addComment(`The method used for upscaling the image. You can query ${V.aiApiUrl}/sdapi/v1/upscalers to see the list of available upscalers.`);
+						.addComment(App.UI.DOM.combineNodes(`The method used for upscaling the image. `, upscalerListSpan));
 				}
 				async function renderQueueOption(clicked = false){
 					const sleep = (ms) => new Promise(r => setTimeout(r, ms));