diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile
index 69bfc25500e1d0fa8ef1e3a547894dcef7f7ab15..797907cd0673ef863e63b71e91f4f20079162873 100755
--- a/.ci/Jenkinsfile
+++ b/.ci/Jenkinsfile
@@ -39,6 +39,7 @@ pipeline {
 				YASHCHIKI_SANDBOXES = "sandboxes"
 				YASHCHIKI_PROXY_HTTP = "http://proxy.kip.uni-heidelberg.de:8080"
 				YASHCHIKI_PROXY_HTTPS = "http://proxy.kip.uni-heidelberg.de:8080"
+				YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME = get_build_cache_on_failure_name()
 				BUILD_CACHE_NAME = "${params.BUILD_CACHE_NAME}"  // propagate parameter to environment
 			}
 			stages {
@@ -83,6 +84,16 @@ pipeline {
 					steps {
 						script {
 							try {
+								// extract options from gerrit comment
+								boolean with_debug = false
+								boolean with_spack_verbose = false
+								if (isTriggeredByGerrit()) {
+									gerrit_comment = jesh(script: "echo '${GERRIT_EVENT_COMMENT_TEXT}' | base64 -d", returnStdout: true)
+									with_debug = gerrit_comment.contains("WITH_DEBUG")
+									with_spack_verbose = gerrit_comment.contains("WITH_SPACK_VERBOSE")
+									env.BUILD_CACHE_NAME = jesh(script: "bash bin/yashchiki_get_build_cache_name.sh", returnStdout: true)
+								}
+
 								sh "python3 bin/yashchiki visionary ${WORKSPACE}/spack singularity_visionary_temp.img " +
 								   "--log-dir=log " +
 								   "--proxy-http=${YASHCHIKI_PROXY_HTTP} " +
@@ -94,7 +105,10 @@ pipeline {
 								   "--host-env-filename=${WORKSPACE}/host.env " +
 								   "--build-cache-name=${BUILD_CACHE_NAME} " +
 								   ("${CONTAINER_BUILD_TYPE}" == "stable" ? "--update-build-cache " : "") +
-								   "--recipe-filename=${WORKSPACE}/visionary_recipe.def"
+								   "--recipe-filename=${WORKSPACE}/visionary_recipe.def " +
+								   "--build-cache-on-failure-name=${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME} " +
+								   (with_debug ? "--debug " : "") +
+								   (with_spack_verbose ? "--spack-verbose " : "")
 							} catch (Throwable t) {
 								archiveArtifacts "errors_concretization.log"
 								throw t
@@ -229,3 +243,7 @@ pipeline {
 		}
 	}
 }
+
+String get_build_cache_on_failure_name() {
+	return (CONTAINER_BUILD_TYPE == "testing" ? "c${GERRIT_CHANGE_NUMBER}p${GERRIT_PATCHSET_NUMBER}" : jesh("echo 'stable_\$(date --iso)'", returnStdout: true))
+}
diff --git a/.ci/Jenkinsfile_asic b/.ci/Jenkinsfile_asic
index b7f8716e2ad6332098c318720472e13003fae119..045b42f8b510050dd10e7e95f8b1bde50b2badde 100755
--- a/.ci/Jenkinsfile_asic
+++ b/.ci/Jenkinsfile_asic
@@ -39,6 +39,7 @@ pipeline {
 				YASHCHIKI_SANDBOXES = "sandboxes"
 				YASHCHIKI_PROXY_HTTP = "http://proxy.kip.uni-heidelberg.de:8080"
 				YASHCHIKI_PROXY_HTTPS = "http://proxy.kip.uni-heidelberg.de:8080"
+				YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME = get_build_cache_on_failure_name()
 				BUILD_CACHE_NAME = "${params.BUILD_CACHE_NAME}"  // propagate parameter to environment
 			}
 			agent { label 'conviz1||conviz2' }
@@ -84,6 +85,16 @@ pipeline {
 					steps {
 						script {
 							try {
+								// extract options from gerrit comment
+								boolean with_debug = false
+								boolean with_spack_verbose = false
+								if (isTriggeredByGerrit()) {
+									gerrit_comment = jesh(script: "echo '${GERRIT_EVENT_COMMENT_TEXT}' | base64 -d", returnStdout: true)
+									with_debug = gerrit_comment.contains("WITH_DEBUG")
+									with_spack_verbose = gerrit_comment.contains("WITH_SPACK_VERBOSE")
+									env.BUILD_CACHE_NAME = jesh(script: "bash bin/yashchiki_get_build_cache_name.sh", returnStdout: true)
+								}
+
 								sh "python3 bin/yashchiki visionary ${WORKSPACE}/spack singularity_asic_temp.img " +
 								   "--log-dir=log " +
 								   "--proxy-${YASHCHIKI_PROXY_HTTP} " +
@@ -96,6 +107,9 @@ pipeline {
 								   "--host-env-filename=${WORKSPACE}/host.env " +
 								   ("${CONTAINER_BUILD_TYPE}" == "stable" ? "--update-build-cache " : "") +
 								   "--recipe-filename=${WORKSPACE}/asic_recipe.def "
+								   "--build-cache-on-failure-name=${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME} " +
+								   (with_debug ? "--debug " : "") +
+								   (with_spack_verbose ? "--spack-verbose " : "")
 							} catch (Throwable t) {
 								archiveArtifacts "errors_concretization.log"
 								throw t
@@ -157,3 +171,7 @@ pipeline {
 		}
 	}
 }
+
+String get_build_cache_on_failure_name() {
+	return (CONTAINER_BUILD_TYPE == "testing" ? "c${GERRIT_CHANGE_NUMBER}p${GERRIT_PATCHSET_NUMBER}" : jesh("echo 'stable_\$(date --iso)'", returnStdout: true))
+}
diff --git a/bin/yashchiki b/bin/yashchiki
index e4c88342ad0fa79ba22d15eb0c6bd8c39070782d..f96f4c1c0ff6703a902f7dae9da216da8bfc17ef 100644
--- a/bin/yashchiki
+++ b/bin/yashchiki
@@ -97,7 +97,11 @@ parser.add_argument(
     "--build-cache-name", type=str, default="default",
     help="Name of build cache to use, resides under "
          "<CACHES_DIR>/build_caches/<BUILD_CACHE_NAME>.")
-
+parser.add_argument(
+    "--build-cache-on-failure-name", type=str,
+    help="Name of build cache to create upon failure, resides under "
+         "<CACHES_DIR>/build_caches/failed/<BUILD_CACHE_NAME> and is "
+         "postfix'ed with an ascending integer.")
 # optional options
 parser.add_argument(
     "--proxy-http", type=str,
@@ -108,6 +112,9 @@ parser.add_argument(
 parser.add_argument(
     "--debug", action="store_true",
     help="Enable debug-level logging.")
+parser.add_argument(
+    "--spack-verbose", action="store_true",
+    help="Enable verbose spack logging.")
 
 args = parser.parse_args()
 
@@ -157,6 +164,7 @@ env = {
     "CONTAINER_STYLE": args.style,
     "CONTAINER_BUILD_TYPE": "testing", # FIXME: should not be required
     "YASHCHIKI_DEBUG": str(int(args.debug)),
+    "YASHCHIKI_SPACK_VERBOSE": str(int(args.spack_verbose)),
     "YASHCHIKI_SANDBOXES": args.sandboxes_dir,
     "YASHCHIKI_IMAGE_NAME": args.output,
     "YASHCHIKI_SPACK_PATH": args.spack_dir,
@@ -173,6 +181,9 @@ if args.proxy_http:
 if args.proxy_https:
     env = env | {"YASHCHIKI_PROXY_HTTPS": args.proxy_https}
 
+if args.build_cache_on_failure_name:
+    env = env | {"YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME": args.build_cache_on_failure_name}
+
 # create directory for logs
 args.log_dir.mkdir(parents=True, exist_ok=True)
 
@@ -239,7 +250,7 @@ with tempfile.TemporaryDirectory(prefix="spack-", dir=env["TMPDIR"]) \
         host_env_filename = temporary_directory.joinpath("host.env")
     env = env | {"YASHCHIKI_HOST_ENV_PATH": host_env_filename}
 
-    run("lib/yashchiki/validate_environment.sh", env)
+    run("lib/yashchiki/store_environment.sh", env)
     run("lib/yashchiki/create_spack_user.sh", env)
     run("lib/yashchiki/create_caches.sh", env)
     run("lib/yashchiki/fetch.sh", env)
diff --git a/bin/yashchiki_create_temporary_build_cache_after_failure.sh b/bin/yashchiki_create_temporary_build_cache_after_failure.sh
index c9c28799ca03e2e6ccef5d257b8811fe5873690b..596b2ac91a2ef992386a60b9b079841c9551da2a 100755
--- a/bin/yashchiki_create_temporary_build_cache_after_failure.sh
+++ b/bin/yashchiki_create_temporary_build_cache_after_failure.sh
@@ -1,25 +1,16 @@
 #!/bin/bash
 
 # This script creates a temporary build cache via symlinks in
-# failed/c<num>p<num>_<num>.
+# failed/${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME}_<num>.
 #
 # It streamlines container deployment as every container deployment will
 # restart at the last sucessfully built package.
 #
 # Echoes path to created cache relative to build_caches base directory.
 
-if [ "${CONTAINER_BUILD_TYPE}" = "stable" ]; then
-    echo "Stable container creation failed, this should not happen." >&2
-    exit 1
-fi
-
-ROOT_DIR="$(dirname "$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")")"
-source "${ROOT_DIR}/lib/yashchiki/get_change_name.sh"
-
 build_num=1
-change_num="$(get_change_name)"
 
-while [ -d "${YASHCHIKI_CACHES_ROOT}/preserved_packages/${change_num}_${build_num}" ]; do
+while [ -d "${YASHCHIKI_CACHES_ROOT}/preserved_packages/${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME}_${build_num}" ]; do
     (( build_num++ ))
 done
 # `build_num` is used to indicate if no preserved packages were found: After
@@ -29,8 +20,8 @@ done
 # store in the failed cache.
 (( build_num-- ))
 
-preserved_packages="${YASHCHIKI_CACHES_ROOT}/preserved_packages/${change_num}_${build_num}"
-failed_build_cache="${YASHCHIKI_CACHES_ROOT}/build_caches/failed/${change_num}_${build_num}"
+preserved_packages="${YASHCHIKI_CACHES_ROOT}/preserved_packages/${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME}_${build_num}"
+failed_build_cache="${YASHCHIKI_CACHES_ROOT}/build_caches/failed/${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME}_${build_num}"
 
 # expects input to be \0-printed
 link_into_failed_buildcache() {
diff --git a/bin/yashchiki_get_build_cache_name.sh b/bin/yashchiki_get_build_cache_name.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fa2d6e6e9e7eca13cc60428186127cf362a25f21
--- /dev/null
+++ b/bin/yashchiki_get_build_cache_name.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+set -euo pipefail
+shopt -s inherit_errexit
+
+ROOT_DIR="$(dirname "$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")")"
+source "${ROOT_DIR}/lib/yashchiki/get_latest_failed_build_cache.sh"
+
+# For testing changesets, see if user supplied a custom build cache with
+# `WITH_CACHE_NAME=<name>`. If not, check if there is a saved build cache from a
+# previous build of this changeset and use that as build cache. If the comment
+# contains `WITHOUT_FAILED_CACHE` we do nothing, i.e. we use the default cache.
+if [ -n "${GERRIT_EVENT_COMMENT_TEXT:-}" ]; then
+
+    tmpfile_comment="$(mktemp)"
+
+    echo "${GERRIT_EVENT_COMMENT_TEXT}" | base64 -d > "${tmpfile_comment}"
+
+    if grep -q "\bWITH_CACHE_NAME=" "${tmpfile_comment}"; then
+        # use specified cache
+        echo "$(sed -nE \
+            -e "s:.*\<WITH_CACHE_NAME=(\S*)(\s|$).*:\1:gp" \
+            "${tmpfile_comment}")"
+        rm "${tmpfile_comment}"
+        exit 0
+    elif ! grep -q "\bWITHOUT_FAILED_CACHE\b" "${tmpfile_comment}"; then
+        latest_failed_build_cache="$(get_latest_failed_build_cache_name)"
+
+        # If there is no previous build cache the while loop will terminate
+        # immedately and build_num be zero.
+        if [ -n "${latest_failed_build_cache}" ]; then
+            echo "${latest_failed_build_cache}"
+            rm "${tmpfile_comment}"
+            exit 0
+        fi
+    fi
+
+    rm "${tmpfile_comment}"
+fi
+
+echo "${BUILD_CACHE_NAME}"
diff --git a/lib/yashchiki/commons.sh b/lib/yashchiki/commons.sh
index b154a4a7ed946901d0c1fc38ea259b57f264d13a..b6c20e66a57f323da104ec3c429db20d25f13bc2 100755
--- a/lib/yashchiki/commons.sh
+++ b/lib/yashchiki/commons.sh
@@ -190,7 +190,7 @@ SPACK_ARGS_INSTALL=()
 SPACK_ARGS_REINDEX=()
 SPACK_ARGS_VIEW=()
 
-if [ -n "$(get_host_env SPACK_VERBOSE)" ]; then
+if [ -n "$(get_host_env YASHCHIKI_SPACK_VERBOSE)" ]; then
     SPACK_ARGS_INSTALL+=("--verbose")
     SPACK_ARGS_VIEW+=("--verbose")
     SPACK_ARGS_REINDEX+=("--verbose")
@@ -512,64 +512,10 @@ _install_from_buildcache() {
     ${MY_SPACK_BIN} "${SPACK_ARGS_REINDEX[@]+"${SPACK_ARGS_REINDEX[@]}"}" reindex
 }
 
-get_latest_failed_build_cache_name() {
-    local full_change_num
-    local possible_build_caches
-    local latest_patch_level
-    local latest_build_num
-
-    full_change_num="$(get_change_name)"
-    change_num="${full_change_num%%p*}"
-    possible_build_caches="$(mktemp)"
-
-    find "${BASE_BUILD_CACHE_FAILED_OUTSIDE}" -mindepth 1 -maxdepth 1 -type d -name "${change_num}*" -print0 \
-        | xargs -r -n 1 -r -0 basename > "${possible_build_caches}"
-
-    if (( $(wc -l <"${possible_build_caches}") == 0 )); then
-        return 0
-    fi
-
-    latest_patch_level="$(cat "${possible_build_caches}" \
-        | cut -d p -f 2 | cut -d _ -f 1 | sort -rg | head -n 1)"
-
-    latest_build_num="$(grep "p${latest_patch_level}_" "${possible_build_caches}" \
-        | cut -d _ -f 2 | sort -rg | head -n 1)"
-
-    echo -n "failed/${change_num}p${latest_patch_level}_${latest_build_num}"
-
-    rm "${possible_build_caches}"
-}
-
-
 #############
 # UTILITIES #
 #############
 
-get_change_name() {
-    local change_num
-    local patch_level
-
-    local gerrit_change_number
-    local gerrit_patchset_number
-    local gerrit_refspec
-
-    gerrit_change_number="$(get_host_env GERRIT_CHANGE_NUMBER)"
-    gerrit_patchset_number="$(get_host_env GERRIT_PATCHSET_NUMBER)"
-    gerrit_refspec="$(get_host_env GERRIT_REFSPEC)"
-
-    if [ -z "${gerrit_change_number:-}" ]; then
-        if [ -n "${gerrit_refspec:-}" ]; then
-            # extract gerrit change number from refspec
-            change_num="$(echo "${gerrit_refspec}" | cut -f 4 -d / )"
-            patch_level="$(echo "${gerrit_refspec}" | cut -f 5 -d / )"
-        fi
-    else
-        change_num="${gerrit_change_number}"
-        patch_level="${gerrit_patchset_number}"
-    fi
-    echo -n "c${change_num}p${patch_level}"
-}
-
 # copied from slurmviz-commons.sh
 get_latest_hash() {
   # Usage: get_latest_hash <pkg-name>
diff --git a/lib/yashchiki/get_latest_failed_build_cache.sh b/lib/yashchiki/get_latest_failed_build_cache.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5850f9bc0d824c7c8ab80da5d84e999914d3b2a4
--- /dev/null
+++ b/lib/yashchiki/get_latest_failed_build_cache.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+set -euo pipefail
+shopt -s inherit_errexit 2>/dev/null || true
+
+ROOT_DIR="$(dirname "$(dirname "$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")")")"
+source ${ROOT_DIR}/lib/yashchiki/get_change_name.sh
+
+get_latest_failed_build_cache_name() {
+    local full_change_num
+    local possible_build_caches
+    local latest_patch_level
+    local latest_build_num
+
+    full_change_num="$(get_change_name)"
+    change_num="${full_change_num%%p*}"
+    possible_build_caches="$(mktemp)"
+
+    find "${YASHCHIKI_CACHES_ROOT}/build_caches/failed" -mindepth 1 -maxdepth 1 -type d -name "${change_num}*" -print0 \
+        | xargs -r -n 1 -r -0 basename > "${possible_build_caches}"
+
+    if (( $(wc -l <"${possible_build_caches}") == 0 )); then
+        rm "${possible_build_caches}"
+        return 0
+    fi
+
+    latest_patch_level="$(cat "${possible_build_caches}" \
+        | cut -d p -f 2 | cut -d _ -f 1 | sort -rg | head -n 1)"
+
+    latest_build_num="$(grep "p${latest_patch_level}_" "${possible_build_caches}" \
+        | cut -d _ -f 2 | sort -rg | head -n 1)"
+
+    echo -n "failed/${change_num}p${latest_patch_level}_${latest_build_num}"
+
+    rm "${possible_build_caches}"
+}
diff --git a/lib/yashchiki/preserve_built_spack_packages.sh b/lib/yashchiki/preserve_built_spack_packages.sh
index dba27fb3ba812a43301105ed21606ad3947fc9d1..5b87548527acdbacb9151f175def59b7b042c34e 100755
--- a/lib/yashchiki/preserve_built_spack_packages.sh
+++ b/lib/yashchiki/preserve_built_spack_packages.sh
@@ -23,16 +23,10 @@ sourcedir="$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")"
 source "${sourcedir}/commons.sh"
 source "${sourcedir}/setup_env_spack.sh"
 
-build_type=$(get_host_env CONTAINER_BUILD_TYPE)
-
 # find empty directory to dump into
 build_num=1
 while /bin/true; do
-    if [ "${build_type}" = "testing" ]; then
-        target_folder="${PRESERVED_PACKAGES_INSIDE}/$(get_change_name)_${build_num}"
-    else
-        target_folder="${PRESERVED_PACKAGES_INSIDE}/${build_type}_$(date --iso)_${build_num}"
-    fi
+    target_folder="${PRESERVED_PACKAGES_INSIDE}/${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME}_${build_num}"
 
     if [ ! -d "${target_folder}" ]; then
         break
diff --git a/lib/yashchiki/store_environment.sh b/lib/yashchiki/store_environment.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9a459f10e8b9ae7977352446566273f8fb7987aa
--- /dev/null
+++ b/lib/yashchiki/store_environment.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -euo pipefail
+shopt -s inherit_errexit
+
+# store environment for usage within container
+echo "# Host environment set to:" >&2
+env | tee "${YASHCHIKI_HOST_ENV_PATH}"
diff --git a/lib/yashchiki/validate_environment.sh b/lib/yashchiki/validate_environment.sh
deleted file mode 100755
index f709216e36f247dacd0f6add09a022d57af8c3dc..0000000000000000000000000000000000000000
--- a/lib/yashchiki/validate_environment.sh
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-shopt -s inherit_errexit
-
-#
-# Some early checks to make sure all needed environment variables are defined.
-#
-if [ "${CONTAINER_BUILD_TYPE}" != "testing" ] && \
-        [ "${CONTAINER_BUILD_TYPE}" != "stable" ]; then
-    echo "CONTAINER_BUILD_TYPE needs to be 'testing' or 'stable'!" >&2
-    exit 1
-fi
-
-if [ "${CONTAINER_BUILD_TYPE}" = "testing" ]; then
-    # In case of testing builds we need to include change number and patchset
-    # level into the final image name. Hence we check beforehand if we have all
-    # information to generate the image name.
-    #
-    # We need to have either:
-    # * both change number AND patchset number
-    # * a refspec from which we extract changeset number and patchset
-    # therefore we have to fail both cases fail.
-    #
-    if [[ ! (( -n "${GERRIT_CHANGE_NUMBER:-}"
-              && -n "${GERRIT_PATCHSET_NUMBER:-}" )
-             || -n "${GERRIT_REFSPEC:-}" ) ]]; then
-        echo -n "Neither GERRIT_REFSPEC nor GERRIT_CHANGE_NUMBER/" >&2
-        echo -n "GERRIT_PATCHSET_NUMBER specified " >&2
-        echo    "for testing build." >&2
-        exit 1
-    fi
-fi
-
-export SPACK_VERBOSE=
-# source file for early validation
-SOURCE_DIR="$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")"
-source "${SOURCE_DIR}/commons.sh"
-
-# For testing changesets, see if user supplied a custom build cache with
-# `WITH_CACHE_NAME=<name>`. If not, check if there is a saved build cache from a
-# previous build of this changeset and use that as build cache. If the comment
-# contains `WITHOUT_FAILED_CACHE` we do nothing, i.e. we use the default cache.
-if [ "${CONTAINER_BUILD_TYPE}" = "testing" ] \
-    && [ -n "${GERRIT_EVENT_COMMENT_TEXT:-}" ]; then
-
-    tmpfile_comment="$(mktemp)"
-
-    echo "${GERRIT_EVENT_COMMENT_TEXT}" | base64 -d > "${tmpfile_comment}"
-
-    if grep -q "\bWITH_DEBUG\b" "${tmpfile_comment}"; then
-        export YASHCHIKI_DEBUG=enabled
-        set_debug_output_from_env
-    else
-        export YASHCHIKI_DEBUG=""
-    fi
-
-    if grep -q "\bWITH_CACHE_NAME=" "${tmpfile_comment}"; then
-        # use specified cache
-        BUILD_CACHE_NAME="$(sed -nE \
-            -e "s:.*\<WITH_CACHE_NAME=(\S*)(\s|$).*:\1:gp" \
-            "${tmpfile_comment}")"
-        export BUILD_CACHE_NAME
-    elif ! grep -q "\bWITHOUT_FAILED_CACHE\b" "${tmpfile_comment}"; then
-        latest_failed_build_cache="$(get_latest_failed_build_cache_name)"
-
-        # If there is no previous build cache the while loop will terminate
-        # immedately and build_num be zero.
-        if [ -n "${latest_failed_build_cache}" ]; then
-            export BUILD_CACHE_NAME="${latest_failed_build_cache}"
-        fi
-    fi
-
-    if grep -q "\bWITH_SPACK_VERBOSE\b" "${tmpfile_comment}"; then
-        export SPACK_VERBOSE="enabled"
-    else
-        export SPACK_VERBOSE=""
-    fi
-
-    rm "${tmpfile_comment}"
-fi
-
-# store environment for usage within container
-echo "# Host environment set to:" >&2
-env | tee "${HOST_ENV_FILE}"