Skip to content

Warn instead of failing when a compat flag is already on by date - #6980

Draft
petebacondarwin wants to merge 1 commit into
mainfrom
pbacondarwin/2026-08-12-compat-flag-warning
Draft

Warn instead of failing when a compat flag is already on by date#6980
petebacondarwin wants to merge 1 commit into
mainfrom
pbacondarwin/2026-08-12-compat-flag-warning

Conversation

@petebacondarwin

@petebacondarwin petebacondarwin commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Problem

Naming a compatibility flag that the Worker's compatibility date already enables was a fatal
configuration error, so workerd serve exited instead of starting:

workerd: service main: The compatibility flag nodejs_compat became the default as of
2026-08-04 so does not need to be specified anymore.

The compiled flag set is identical whether or not the flag is listed, so the redundancy is worth
pointing out but is not a reason to refuse to run. This became a common papercut once
nodejs_compat gained a default-on date of 2026-08-04: configs that had always listed the flag
explicitly stopped loading as soon as their compatibility date advanced past it.

Change

ValidationErrorReporter gains addWarning() for configuration problems that don't prevent the
Worker from running, and the redundant-flag diagnostic moves onto it.

The part worth reviewing carefully is that addWarning()'s default implementation forwards to
addError()
. A reporter that hasn't decided how to surface warnings therefore keeps rejecting the
configuration rather than silently accepting it — treating a warning as non-fatal is an explicit
opt-in. That keeps this PR's blast radius inside this repo: I audited every reporter implemented
outside it, including the ones behind Cloudflare's deploy-time validation and Worker startup, and
all of them inherit the default and so behave exactly as they do today. Relaxing those paths is a
separate follow-up.

The Server constructor gains a parameter, but nothing outside this repo constructs it, so the
signature change is contained here too.

workerd's own reporters opt in:

Reporter Warning goes to
Server::ConfigErrorReporter new warning sink on Servercontext.warning() in the CLI, so it honours --structured-logging
Server::DynamicErrorReporter, WorkerLoader KJ_LOG(WARNING) — a dynamically-loaded Worker has no config file to point at
SimpleWorkerErrorReporter collected into a warnings vector alongside errors
MockErrorReporter (test fixture) deliberately left on the default, so a stray warning still hard-fails unit tests

The check stays suppressed under FUTURE_FOR_TEST, where it would fire for nearly every test:
wd_test runs each test at both the oldest and the newest compatibility date.

Testing

  • compatibility-date-test: the existing redundant-flag case moves from expectedErrors to a new
    expectedWarnings (which also newly asserts the resulting flag set, confirming the flag is still
    applied). Adds coverage for the CODE_VERSION path, the $compatEnableAllDates message variant,
    and FUTURE_FOR_TEST staying silent.
  • server-test: new end-to-end case asserting the Worker actually starts, serves, and emits the
    warning.
  • Both new assertions were confirmed red before green.
  • Full suite: 1620/1621 pass. The one failure, inspector-test, is a pre-existing flake — it fails
    roughly 1-in-8 runs against an identical prebuilt binary, and its config is on compatibility date
    2024-01-01 with nodejs_compat, so no warning fires for it.

Naming a compatibility flag that the Worker's compatibility date already
enables produced a fatal configuration error, so `workerd serve` exited
rather than starting. The compiled flag set is identical either way, so the
redundancy is worth pointing out but is not a reason to refuse to run. This
became a common papercut once `nodejs_compat` gained a default-on date of
2026-08-04, since configs that had always listed the flag explicitly stopped
loading as soon as their compatibility date advanced past it.

ValidationErrorReporter gains `addWarning()` for configuration problems that
do not prevent the Worker from running. Its default implementation forwards
to `addError()`, so a reporter that has not decided how to surface warnings
keeps rejecting the configuration rather than silently accepting it; treating
a warning as non-fatal is an explicit opt-in.

workerd's own reporters opt in. Services from a config file report through a
new warning sink on Server, which the CLI prints via the process context so
it honours --structured-logging. Dynamically-loaded Workers log to the
process log instead, having no config file to point the developer at.

The check stays suppressed under FUTURE_FOR_TEST, where it would otherwise
fire for nearly every test, because wd_test runs each test at both the oldest
and the newest compatibility date.
@ask-bonk

ask-bonk Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

APIError: Invalid Anthropic API Key

github run

2 similar comments
@ask-bonk

ask-bonk Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

APIError: Invalid Anthropic API Key

github run

@ask-bonk

ask-bonk Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

APIError: Invalid Anthropic API Key

github run

@ask-bonk

ask-bonk Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@petebacondarwin Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@dom96 dom96 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things that need to be changed, but almost ready to go.

I would also suggest creating a validator test in EW for this. Just to make sure validations aren't broken by this (which as things stand would happen I think).

// how to surface warnings therefore keeps rejecting the configuration rather than silently
// accepting it; treating a warning as non-fatal is an explicit opt-in.
virtual void addWarning(kj::String warning) {
addError(kj::mv(warning));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any validation report with an error is treated as a failed validation. So this will prevent deployment of workers that have a warning.

We could hook this up through EWC, by adding a new warnings field in the ValidationReport, but that would require changes in EW and EWC. So I think it's fine to simply drop it here: no need to give users this warning when they deploy, just when they run the worker locally.

Comment on lines +407 to +412
// A dynamically-loaded Worker has no configuration file to point the developer at, so the
// process log is the only place left to say anything.
for (auto& warning: errorReporter.warnings) {
KJ_LOG(WARNING, warning);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already log a warning in src/workerd/server/server.c++. This shouldn't be necessary here (and actually may cause problems for the validator).

@dom96

dom96 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Also we should make sure Bonk runs on this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants