diff --git a/.ci/bootstrap_spack.sh b/.ci/bootstrap_spack.sh
index 662ea3a4dca2601a6a4c89462e9c175363291ddb..a4b9e0cc581b7316b2c5f8c2cb1d5ea7d937ecae 100755
--- a/.ci/bootstrap_spack.sh
+++ b/.ci/bootstrap_spack.sh
@@ -41,7 +41,7 @@ install_from_buildcache "${spack_bootstrap_dependencies[@]}"
 
 # We install all packages needed by boostrap here
 for bootstrap_spec in "${spack_bootstrap_dependencies[@]}"; do
-    ${MY_SPACK_BIN} "${SPACK_ARGS_INSTALL[@]}" install --no-cache --show-log-on-error "${bootstrap_spec}"
+    ${MY_SPACK_BIN} "${SPACK_ARGS_INSTALL[@]+"${SPACK_ARGS_INSTALL[@]}"}" install --no-cache --show-log-on-error "${bootstrap_spec}"
 done
 
 num_packages_pre_boostrap="$(${MY_SPACK_BIN} find 2>&1 | head -n 1 | awk '/installed packages/ { print $2 }')"
diff --git a/.ci/commons.sh b/.ci/commons.sh
index 65c3b20fe45d747e5d428e61fcee2ac41a6bb99e..0ef7a1b83d4a44d354cd030c09fb9104cd7086d8 100755
--- a/.ci/commons.sh
+++ b/.ci/commons.sh
@@ -149,7 +149,7 @@ if [[ ! -v _yashchiki_exit_fns[@] ]]; then
     _yashchiki_exit_fns=()
 
     _yashchiki_exit_trap() {
-        for fn in "${_yashchiki_exit_fns[@]}"; do
+        for fn in "${_yashchiki_exit_fns[@]+"${_yashchiki_exit_fns[@]}"}"; do
             eval "${fn}"
         done
     }
@@ -282,11 +282,11 @@ done | tr '\n' ' '
 # (defined above)
 spack_add_to_view_with_dependencies["${VISIONARY_GCC}"]="no"
 spack_add_to_view["${VISIONARY_GCC}"]="$(
-    for viewname in "${spack_views[@]}"; do
+    for viewname in "${spack_views[@]+"${spack_views[@]}"}"; do
         # check if the current view matches any view that does not get the
         # default gcc
         # Note: Currently this allow partial matches
-        if printf "%s\n" "${spack_views_no_default_gcc[@]}" \
+        if printf "%s\n" "${spack_views_no_default_gcc[@]+"${spack_views_no_default_gcc[@]}"}" \
                 | grep -qF "${viewname}"; then
             continue
         fi
@@ -349,7 +349,7 @@ populate_views() {
         local dependencies="${spack_add_to_view_with_dependencies["${addition}"]}"
         {
             for viewname in ${spack_add_to_view["${addition}"]}; do
-                echo "${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[*]} view -d ${dependencies} symlink -i \"${MY_SPACK_VIEW_PREFIX}/${viewname}\" \"${addition}\""
+                echo "${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[*]+"${SPACK_ARGS_VIEW[*]}"} view -d ${dependencies} symlink -i \"${MY_SPACK_VIEW_PREFIX}/${viewname}\" \"${addition}\""
             done
         } | parallel_cmds
     done
@@ -583,7 +583,7 @@ _install_from_buildcache() {
         | xargs dirname | sort | uniq )
 
     # ensure all toplevel directories exist
-    for dir in "${toplevel_dirs[@]}"; do
+    for dir in "${toplevel_dirs[@]+"${toplevel_dirs[@]}"}"; do
         [ ! -d "${dir}" ] && mkdir -p "${dir}"
     done
 
@@ -591,7 +591,7 @@ _install_from_buildcache() {
         < "${FILE_HASHES_TO_INSTALL_FROM_BUILDCACHE}"
 
     # have spack reindex its install contents to find the new packages
-    ${MY_SPACK_BIN} "${SPACK_ARGS_REINDEX[@]}" reindex
+    ${MY_SPACK_BIN} "${SPACK_ARGS_REINDEX[@]+"${SPACK_ARGS_REINDEX[@]}"}" reindex
 }
 
 get_latest_failed_build_cache_name() {
diff --git a/.ci/install_visionary_spack.sh b/.ci/install_visionary_spack.sh
index d5ab21c5233e19649320ca825bc1178eefd9f987..980cee741e9f6c4727c208eb432de6a4e8c33080 100755
--- a/.ci/install_visionary_spack.sh
+++ b/.ci/install_visionary_spack.sh
@@ -11,10 +11,10 @@ source "${sourcedir}/setup_env_spack.sh"
 
 cd "$HOME"
 
-install_from_buildcache "${spack_packages[@]}"
+install_from_buildcache "${spack_packages[@]+"${spack_packages[@]}"}"
 
 echo "INSTALLING PACKAGES"
-for package in "${spack_packages[@]}"; do
+for package in "${spack_packages[@]+"${spack_packages[@]}"}"; do
     # Disable cache because we already installed from build cache.
     # Also there is a bug that when `--no-cache` is not specified, install will
     # fail because spack checks for signed buildcache packages only.
@@ -25,7 +25,7 @@ for package in "${spack_packages[@]}"; do
         exit 1
     fi
     echo "Installing: ${package}" >&2
-    ${MY_SPACK_BIN} "${SPACK_ARGS_INSTALL[@]}" install --no-cache --show-log-on-error --file "${specfile}"
+    ${MY_SPACK_BIN} "${SPACK_ARGS_INSTALL[@]+"${SPACK_ARGS_INSTALL[@]}"}" install --no-cache --show-log-on-error --file "${specfile}"
 done
 
 # create the filesystem views (exposed via singularity --app option)
@@ -53,29 +53,29 @@ cat <<EOF
 # Packages still plagued by gccxml #
 ####################################
 
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-wafer $(get_latest_hash visionary-wafer+dev~gccxml)
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-wafer-nodev $(get_latest_hash visionary-wafer~dev~gccxml)
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-wafer $(get_latest_hash visionary-wafer+dev~gccxml)
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-wafer-nodev $(get_latest_hash visionary-wafer~dev~gccxml)
 
 ##################################################
 # Strong independent packages who need no gccxml #
 ##################################################
 
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-simulation $(get_latest_hash "visionary-simulation+dev")
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-simulation-nodev $(get_latest_hash "visionary-simulation~dev")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-simulation $(get_latest_hash "visionary-simulation+dev")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-simulation-nodev $(get_latest_hash "visionary-simulation~dev")
 
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dls-core $(get_latest_hash visionary-dls-core "^${DEPENDENCY_PYTHON3}")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dls-core $(get_latest_hash visionary-dls-core "^${DEPENDENCY_PYTHON3}")
 
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dls $(get_latest_hash visionary-dls+dev "^${DEPENDENCY_PYTHON3}")
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dls-nodev $(get_latest_hash visionary-dls~dev "^${DEPENDENCY_PYTHON3}")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dls $(get_latest_hash visionary-dls+dev "^${DEPENDENCY_PYTHON3}")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dls-nodev $(get_latest_hash visionary-dls~dev "^${DEPENDENCY_PYTHON3}")
 
 # slurvmiz needs no dev-tools because it is not for end-users
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-slurmviz $(get_latest_hash "visionary-slurmviz %${VISIONARY_GCC}")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-slurmviz $(get_latest_hash "visionary-slurmviz %${VISIONARY_GCC}")
 
 #############
 # dev tools #
 #############
 
-${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dev-tools $(get_latest_hash "${SPEC_VIEW_VISIONARY_DEV_TOOLS}")
+${MY_SPACK_BIN} ${SPACK_ARGS_VIEW[@]+"${SPACK_ARGS_VIEW[@]}} view -d yes symlink -i ${MY_SPACK_VIEW_PREFIX}/visionary-dev-tools $(get_latest_hash "${SPEC_VIEW_VISIONARY_DEV_TOOLS}")
 EOF
 } | parallel_cmds