Skip to content
Latchkey LogoLatchkey home

GitHub Actions Missing environment production, and what really happens

Searching for GitHub Actions missing environment production usually means a deploy job named an environment and something went wrong, but naming an environment that does not exist is not one of the things that fails. The documentation is explicit that running a workflow which references an environment that does not exist creates one, with no protection rules and no secrets.

What a deploy job receives when it names a known environment against an unknown one
Naming an unknown environment is not refused. The job gets a new one with nothing configured, which is why the failure appears later as an empty secret.

What this error means

A deploy job runs when you expected it to be gated. Reviewers are never asked, the wait you configured does not happen, and every secret the job reads from the environment comes back empty, so the deployment either fails at the credential step or, worse, succeeds against the wrong target using a fallback. Nothing is annotated, because from the platform's point of view the job named an environment and got one.

Illustrative job fragment, not a log line
jobs:
  deploy:
    environment: production   # misspelled or never created
    runs-on: ubuntu-latest
# no error, a new empty environment is created instead

What the documentation says happens

The page on managing environments states it in one sentence: running a workflow that references an environment that does not exist will create an environment with the referenced name. It goes on to describe what that new environment holds, which is nothing. Unless it was created by an implicit Pages build, it has no protection rules and no secrets configured.

The same paragraph records who may do this. Anyone who can edit workflows in the repository can create environments through a workflow file, while only repository administrators can configure one. So the creation path is open to every contributor and the configuration path is not, which is exactly the combination that produces an unprotected environment nobody meant to make.

That is why a misspelled name produces silence rather than a failure. The reference resolved, in the sense that something now exists with that name. What did not survive is everything you actually wanted from it.

The job namesWhat the job getsHow you notice
an environment that existsits rules, its secrets, its URLthe gates behave as configured
a name that does not exista new environment with nothing in itempty secrets, no reviewers asked
a name differing only in casedepends on the existing entrycheck the environments list for near duplicates
no environment at allno environment scoped valuesa different message, from Pages, if deploying there

Common causes

The environment name in the job does not match the configured one

A typo, a plural, an abbreviation, or a difference in case. Nothing rejects it, so the job proceeds against a brand new environment that has no rules and no secrets, and the first visible symptom is an empty credential.

The environment was never created in the repository at all

A workflow copied from another repository brings the environment name with it and not the environment. The first run creates the name, which is why the second person to look sees an environment that exists and still does not work.

The secrets are configured at a different scope

Environment secrets are read per job and only for the environment the job names. A value saved as a repository secret is not an environment secret, and a job that names the wrong environment will not find it either way. That is the subject of its own page in this hub.

The job was expected to fail without an environment and did not

In our experience this belief comes from Pages. A Pages deploy job with no environment key does produce an error from the deployments endpoint, and people generalize it into a rule about environments that does not hold anywhere else.

How to fix it

List the environments and compare them to the job

  1. List the repository's environments through the API or the settings page.
  2. Look for near duplicates that differ by case, a plural or an abbreviation.
  3. Compare each one against the environment: value in every job that names one.
  4. Delete the accidental entry after you have pointed the job at the right one.

Read the environment name from a single source

Put the name in one place and reference it, rather than retyping it in each workflow. A repository variable read through the vars context works, and so does a reusable workflow that owns the deploy job. Either removes the opportunity for one file to drift.

.github/workflows/deploy.yml (illustrative)
jobs:
  deploy:
    environment: ${{ vars.DEPLOY_ENVIRONMENT }}
    runs-on: ubuntu-latest

Confirm the gate rather than assuming it

If the environment is supposed to require a reviewer, prove it once by opening a run and watching it wait. A deploy that has never paused is either correctly configured and never triggered a rule, or attached to an environment that has no rules, and those two look identical from the outside.

When the message really is about a Pages deployment, read that page

A status 400 from the deployments endpoint, surfaced by actions/deploy-pages, is a different problem with a different fix, and it fires when the deploy job has no environment key rather than an unfamiliar one. Follow the related link rather than renaming environments.

Where the phrase people search for actually comes from

There is a real string containing the words missing environment, and tracing it matters because it has been attached to the wrong explanation. It appears in logs of jobs using actions/deploy-pages, in the middle of a longer line about failing to create a deployment, and the part of the line that carries the words is not written by the action at all.

The action builds its message in the error branch of its deployment module. It composes a sentence naming the status and the build version, appends the request id when the response carries one, and then for a status of 400 it appends the words Responded with followed by the server's own message. So on a 400, everything after that point is the Pages deployments endpoint speaking, passed through verbatim.

What the server says there is that an environment is missing and that the workflow's deployment job should have one, with a worked example. That is the opposite complaint from the one this page started with: it is raised when the job has no environment: key at all, not when the key names something unfamiliar. Our page on deploy-pages failing to create a deployment owns that message family and explains the per-status sentences.

Finding the environment you actually created

Because the creation is silent, the fastest confirmation is to list the repository's environments and look for a near duplicate. A list containing both production and Production, or both production and prod, tells you immediately that a workflow created one of them and that your rules are attached to the other.

Environment names are worth treating as a small, closed vocabulary for this reason. A repository with three environments and every workflow naming one of the three has no room for this failure, whereas a repository where each workflow invents its own has no way to notice.

When the environment is genuinely new and you meant it, remember the second half of the documentation's sentence: only an administrator can configure it. Creating it through a workflow gets you the name and nothing else, so the protection rules and secrets still have to be added deliberately.

Terminal
gh api repos/OWNER/REPO/environments --jq '.environments[].name'

Why there is no recorded run on this page

The whole finding is that nothing fails, so a recorded run would be green and would prove the absence of an error by showing the absence of an error, which is the weakest possible evidence. The thing that actually changes is the repository's environments list, which is a settings surface rather than a job artifact, and no log line is written when it changes.

There is also a reason not to stage it. Producing the evidence means deliberately creating an unprotected environment on a real repository, and the documentation notes that only an administrator can configure one afterwards, so the prop would outlive the recording as a misleading entry in a settings page. The documented sentence and the traced status-400 passthrough answer the question without leaving anything behind.

How to prevent it

  • Keep environment names in one place and reference them from every workflow.
  • Review the repository's environments list after adding a deploy job.
  • Treat an empty environment secret as a name mismatch until you have ruled it out.
  • Have an administrator configure protection rules the same day an environment appears.

Frequently asked questions

Does GitHub Actions fail a job that names an environment that does not exist?
No. The documentation states that running a workflow which references an environment that does not exist will create one with that name. The new environment has no protection rules and no secrets unless it was created by an implicit Pages build, so the job runs ungated instead of failing.
Where does the "Missing environment" message actually come from?
From the Pages deployments endpoint, passed through by actions/deploy-pages. On a status 400 the action appends the words Responded with and then the server's own message, so that text is the API speaking. It means the deploy job has no environment: key at all, which is a different problem from naming an unfamiliar one.
Why are my environment secrets empty when the environment exists?
Most often because the job names a different environment from the one holding the secrets, and the mismatch created a second, empty environment. List the environments and look for near duplicates before changing anything about the secrets themselves.
Who can create and configure an environment?
The documentation says that anyone who can edit workflows in the repository can create environments through a workflow file, and that only repository administrators can configure them. That split is why an accidental environment appears with nothing in it and stays that way.

Related guides

References

A typo in an environment name creates one with no rules. Latchkey runs the deploy at $0.0025/min. Start free → 30-day trial · No credit card