930 words
5 minutes

GitHub Actions Boolean Input Runs When False? Use the inputs Context

2026-08-02
2026-08-21
DevOps
GitHub Actions
/
CI/CD
/
DevOps
/
Automation

A GitHub Actions job can run even when a workflow_dispatch checkbox is cleared. The usual cause is an if condition that reads github.event.inputs.deploy: the event payload contains the string 'false', and a non-empty string is truthy in an Actions conditional. Use the typed inputs.deploy Boolean instead.

The primary rule is small but important: define the input as boolean, then use inputs.<name> in an if expression. Reserve github.event.inputs for cases where you intentionally need its string representation.

Define the deploy decision as a boolean#

workflow_dispatch lets a workflow expose typed inputs in the Actions UI. For an operation that writes to a deployment environment, make the decision explicit and default it to false:

name: Manual deploy
on:
workflow_dispatch:
inputs:
deploy:
description: 'Deploy the current ref?'
required: true
default: false
type: boolean
environment:
description: 'Target environment'
required: true
type: environment
jobs:
deploy:
if: ${{ inputs.deploy }}
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh

GitHub documents boolean and environment as supported workflow_dispatch input types. The workflow file must be on the repository’s default branch before the manual trigger is available. If this is a production workflow, keep the environment protections and permissions in the same review—not in a later cleanup.

Why github.event.inputs can run the wrong branch#

Both contexts receive the submitted values, but their types differ. inputs.deploy remains a Boolean; github.event.inputs.deploy becomes the string 'true' or 'false'.

jobs:
safe-deploy:
if: ${{ inputs.deploy }}
runs-on: ubuntu-latest
steps:
- run: ./scripts/deploy.sh
unsafe-deploy:
if: ${{ github.event.inputs.deploy }}
runs-on: ubuntu-latest
steps:
- run: ./scripts/deploy.sh

In the second job, a non-empty string is not the same thing as the Boolean value false. The practical result is a condition that is harder to reason about and easy to copy into a deployment workflow by mistake. GitHub’s workflow syntax reference explicitly distinguishes the two contexts and calls out Boolean preservation in inputs.

If you inherit a workflow that cannot switch contexts immediately, compare the event value as a string instead of relying on its truthiness:

if: ${{ github.event.inputs.deploy == 'true' }}

That is a compatibility measure, not the preferred shape for new manually triggered workflows.

Pick the condition by input source#

The right expression depends on where the value came from. Do not treat every value named deploy as a Boolean.

Value sourceRuntime typeCondition to use
workflow_dispatch input through inputs.deployBooleanif: ${{ inputs.deploy }}
The same input through github.event.inputs.deployStringif: ${{ github.event.inputs.deploy == 'true' }}
A string stored in env.DEPLOYStringif: ${{ fromJSON(env.DEPLOY) }} when the value is valid JSON true or false
A workflow shared by workflow_dispatch and workflow_callTyped through the unified inputs contextPrefer if: ${{ inputs.deploy }}

GitHub’s expression rules list false, empty strings, zero, and null as falsy. The string 'false' is not on that list: it is a non-empty string. That distinction explains why this condition can select a job even though the Actions form showed a cleared checkbox:

if: ${{ github.event.inputs.deploy }}

Use fromJSON() only at a boundary where you genuinely receive a string, such as an environment variable or step output. Do not add conversion around inputs.deploy; it is already a Boolean.

Keep strings at the command boundary#

Shell environment variables are strings, even when the expression that supplies one came from a Boolean input. Put the typed decision in the job or step if; pass values to a command only after the job is already selected.

jobs:
deploy:
if: ${{ inputs.deploy }}
runs-on: ubuntu-latest
steps:
- name: Deploy selected environment
env:
TARGET_ENVIRONMENT: ${{ inputs.environment }}
run: ./scripts/deploy.sh "$TARGET_ENVIRONMENT"

This separates two jobs that are often confused: the expression decides whether deployment is permitted to run, while the shell variable supplies an argument to a command that is already running. Treating a shell variable as the source of the deploy decision brings the string-conversion problem back.

Reproduce the type difference without deploying#

Before attaching a real deploy command, add a temporary job that prints both values through toJSON(). The JSON form makes the type difference visible: the typed context prints false, while the event context prints "false".

jobs:
inspect-inputs:
runs-on: ubuntu-latest
steps:
- name: Show submitted input objects
run: |
printf 'inputs.deploy=%s\n' '${{ toJSON(inputs.deploy) }}'
printf 'github.event.inputs.deploy=%s\n' '${{ toJSON(github.event.inputs.deploy) }}'

With the checkbox clear, the relevant output shape is:

inputs.deploy=false
github.event.inputs.deploy="false"

Run the workflow twice from the Actions tab—once with the checkbox clear and once selected. This verifies both branches without executing a deployment. Then remove the diagnostic job or keep it limited to non-sensitive input names. Do not print secrets or assume GitHub masks every value that merely resembles a secret.

If this manual workflow builds a static Astro site before deployment, Dockerize an Astro Static Site: Build dist, Serve It with Caddy shows a reproducible build-and-serve boundary. Keep that build step behind the same typed deploy gate.

The decision is mechanical: use inputs.deploy when the workflow owns a typed input, compare github.event.inputs.deploy with 'true' only for compatibility, and convert string boundaries explicitly. A cleared checkbox must produce a Boolean false at the condition that guards deployment.

FAQ#

Q: Can I use github.event.inputs for a workflow_dispatch checkbox?#

A: Yes, but it is a string context. Compare it explicitly with 'true' if you must use it. For a new Boolean condition, use inputs.<name> so the workflow expression receives a Boolean value.

Q: Why does the string ‘false’ run a GitHub Actions job?#

A: GitHub Actions conditionals treat non-empty strings as truthy. The event payload stores a manual Boolean input as the string 'false', so use the typed inputs context or compare the event string explicitly with 'true'.

Q: Why is the Run workflow button missing?#

A: GitHub documents that workflow_dispatch receives events only when its workflow file is on the default branch. Check that branch before debugging the YAML input definition.

References:

GitHub Docs: Workflow syntax for GitHub Actions

GitHub Docs: Contexts reference

GitHub Docs: Evaluate expressions in workflows and actions

GitHub Docs: Triggering a workflow

GitHub Actions Boolean Input Runs When False? Use the inputs Context
https://laplusda.com/en/posts/github-actions-workflow-dispatch-boolean-inputs/
Author
Zero
Published at
2026-08-02
License
CC BY-NC-SA 4.0
Was this article useful?

Report a typo or broken link, or suggest a related topic.