Skip to content

wrangler deploy --var NAME:VALUE does not override baked-in vars.NAME in config file (wrangler 4.123.0) #15197

Description

@AleksNeStu

Summary

wrangler deploy --var NAME:VALUE does not override a baked-in vars.NAME value in the wrangler config file. The config-file value wins. This is reproducible on wrangler@4.123.0 (and was also present on 4.101.x as far as I traced).

Reproduction

Minimal wrangler.toml (or .jsonc):

name = "test-var-override"
main = "src/index.js"
compatibility_date = "2025-01-01"

[vars]
FOO = "from-config"

Minimal src/index.js:

export default {
  async fetch(request, env) {
    return new Response(JSON.stringify({ FOO: env.FOO }));
  }
}

Then:

npx wrangler@4.123.0 deploy --var "FOO:from-cli"
# In another shell:
curl https://test-var-override.<acct>.workers.dev
# → { "FOO": "from-config" }   <-- WRONG (config-file value won)

Expected

The CLI --var should override the config-file vars entry, just like every other wrangler config layer does. The result should be:

{ "FOO": "from-cli" }

Actual

{ "FOO": "from-config" }

This is a meaningful behavioural surprise. Users (including me) reasonably assume --var NAME:VALUE is the runtime override — it's the only way to set per-deploy values without committing a config change. The current behaviour silently discards the override, which is the worst possible failure mode for a CLI flag.

Versions tested

  • wrangler@4.123.0 (latest stable as of 2026-08-14) — bug present
  • wrangler@4.101.x (earlier version I worked with) — bug present
  • Reproduction is config-format-agnostic (TOML and JSONC both exhibit it)

Workaround (verified working in our production deploy)

wrangler secret put NAME <<< VALUE writes to the server-side secret store, which is a different code path from vars and is not shadowed by config-file entries. The catch: secrets are encrypted at rest and intended for sensitive values, so using them for non-sensitive per-deploy values (e.g. COMMIT_SHA) is semantically wrong and incurs an extra API call per deploy. I had to switch our CI deploy from --var to secret put because the former is silently broken in this version.

Impact

Anyone using wrangler deploy --var to inject per-deploy metadata (commit SHA, deploy ID, build number, feature flags) is getting the wrong value at runtime and may not have noticed because the override value is usually similar to the config default. Worst-case: a deploy pipeline reports "deploy v1.2.3 succeeded" while the live Worker is still on the v1.2.2 value (or whatever was last hard-coded in the config).

Suggested fix

The --var parsing path should take precedence over the config-file vars entry (or at minimum the two should compose, with the CLI value winning on conflict). I haven't dug into the source, but my guess is the config-file vars block is being merged into env first and the --var argument is being applied as an additive append without overriding existing keys.

Cross-reference

Affects a production deploy pipeline built on Cloudflare Workers Static Assets. Filed from investigation of a version: "unknown" regression that we traced to this exact bug — we now use wrangler secret put as a workaround.

Happy to provide a test case in the wrangler test suite if that helps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status
    Untriaged

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions