Matched signals
- The 'set-env' command is deprecated
- set-env' command is disabled
- Unable to process command '::set-env'
- ::set-env name=
- Unprocessed element 'set-env'
GitHub Actions environment variable not persisted across steps
What this failure means
A GitHub Actions step exported an environment variable using the deprecated
::set-env workflow command, which is now disabled. The variable was not
visible to subsequent steps. The fix is to write to $GITHUB_ENV instead.
Symptoms
Faultline looks for one or more of these log fragments:
The 'set-env' command is deprecated
set-env' command is disabled
Unable to process command '::set-env'
::set-env name=
Unprocessed element 'set-env'
Diagnosis
GitHub Actions runs each run: step in a new shell process. Variables set
with the shell’s export built-in do not persist across steps. To share
a value with subsequent steps, write to the $GITHUB_ENV file:
echo "MY_VAR=value" >> "$GITHUB_ENV"
Before this mechanism existed, GitHub Actions supported a workflow command
syntax (::set-env name=VAR::value). This command was deprecated in
October 2020 and permanently disabled due to a security vulnerability
(it allowed injection from log output into the runner’s environment). Any
workflow still using it receives an explicit error:
The 'set-env' command is deprecated and will be disabled soon.Unable to process command '::set-env' successfully.Error: Unprocessed element 'set-env'
The downstream symptom is that the variable appears empty in later steps, causing the following step to fail with a command-not-found, missing-path, or empty-value error.
Fix steps
-
Search the workflow file for any use of the
::set-envsyntax:grep -r "::set-env" .github/workflows/ -
Replace each occurrence with the
$GITHUB_ENVfile append:# Before (deprecated / disabled): echo "::set-env name=MY_VAR::$VALUE" # After (correct): echo "MY_VAR=$VALUE" >> "$GITHUB_ENV" -
If
export VAR=valueis used to set a variable that needs to be visible in a later step, replace it:# Before (does not persist across steps): export MY_VAR=$(git describe --tags) # After (persists to all subsequent steps in the same job): echo "MY_VAR=$(git describe --tags)" >> "$GITHUB_ENV" -
For step outputs (not environment variables), use
$GITHUB_OUTPUT:echo "result=success" >> "$GITHUB_OUTPUT"Then reference the output in a later step with
${{ steps.<step-id>.outputs.result }}. -
Re-run the workflow and confirm the variable is available in subsequent steps.
Validation
-
Add a diagnostic step immediately after the setting step:
echo "MY_VAR is: $MY_VAR" -
Confirm the value is printed correctly, not empty.
-
Confirm the
::set-enverror no longer appears in the workflow log.
Why it matters
Shell environment variables are process-local. GitHub Actions runs each step
in its own process, so export and ::set-env both silently drop values
between steps. Developers migrating from other CI systems or writing their
first GitHub Actions workflow regularly hit this because the mental model
of a shared shell session does not apply.
The ::set-env command was disabled as a security fix: a compromised
dependency or a log line from a build tool could inject arbitrary environment
variable values into the runner’s environment. Replacing it with $GITHUB_ENV
uses a file path that is unique per job run and not guessable from log output.
Prevention
- Use
>> "$GITHUB_ENV"for all inter-step environment variable sharing. - Use
>> "$GITHUB_OUTPUT"for step outputs passed to other steps or jobs. - Enable the
actions/checkoutpre-commit hook or a workflow linter (e.g.,actionlint) to catch::set-envusage in code review.
Try it locally
grep -r "::set-env" .github/workflows/
grep -r "::set-output" .github/workflows/
grep -r "::set-env" .github/workflows/ && echo "FOUND deprecated usage" || echo "Clean"
How Faultline detects it
Use faultline explain github-actions-env-not-persisted to see the full playbook.
faultline analyze build.log
faultline explain github-actions-env-not-persisted
Generated from playbooks/bundled/log/ci/github-actions-env-not-persisted.yaml. Do not edit directly.