Skip to content

fix(compute): hold invalid settings outside the dedicated gateway tool policy as gateway-config - #4316

Merged
freeqaz merged 3 commits into
mainfrom
fix-3045
Oct 31, 2026
Merged

freeqaz merged 3 commits into
mainfrom
fix-3045

Conversation

@freeqaz

@freeqaz freeqaz commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

A dedicated Gateway (Codex, or a dedicated OpenClaw worker) composes its tool policy and runs openclaw config validate --json before OpenClaw starts. Every invalid report was held as gateway-tool-policy (INCOMPATIBLE_RESPONSE) with one log line: "The dedicated Gateway cannot apply its required tool policy. It remains unready; use the supporting OCE runtime image and a valid Gateway tool allowlist."

So a Dedicated Codex Agent whose Configuration had an invalid plugin entry (a beam entry without mirror.endpoint/mirror.catalogs, even with enabled: false) failed fast, but the log gave the wrong cause and the wrong next step, and named no setting. An embedded Gateway with the same entry already logs the right line since #4313 (check gateway-config).

Change

  • gateway-tool-policy.ts: when the validator reports valid: false and no issue concerns a setting the tool policy step composes, the step now holds check gateway-config (code UNAVAILABLE). The composed settings are tools.gatewayPolicy, agents.defaults.modelSelectionScope, cron.triggers.enabled and plugins.entries.codex.config.codexDynamicToolsExclude.
    • An issue counts as the step's own when its path is one of those settings or lies under one. It also counts when its path is a parent of one and the message names that setting's key as refused, which is how a runtime without the setting reports it (Unrecognized key: "enabled" at cron.triggers).
    • These cases keep the gateway-tool-policy hold as before: an issue with no setting path (<root>), a report with no issues, a validator that failed or printed no report, a policy that composition itself refuses, and an unknown runtime source. The gateway-state-lock hold (finding 2864) is unchanged.
  • The log line is the one fix(compute): hold a gateway configuration openclaw refuses at startup #4313's embedded hold writes, from one shared helper (invalidOpenClawConfigurationLine next to openClawConfigIssues, both now in the provider-neutral compute/openclaw-config-issues.ts, so Docker does not import them from the Kubernetes provider): up to five setting paths, schema messages only where they carry no value, and the same remedy. Only the opening differs: "The OpenClaw Gateway did not start, and OpenClaw reports its configuration invalid (...)". fix(compute): hold a gateway configuration openclaw refuses at startup #4313's hold now builds its line with the same helper, and its text does not change.
  • The Docker dedicated wrapper embeds the same helper, so it holds the same check.
  • Same check name and code, already in the runtime failure vocabulary. Only the contract's comment changes, and the Compute/worker contract does not.
  • Docs: one sentence each in the managed native configuration reference and the deployment diagnostics flow (with a changelog entry), where fix(compute): hold a gateway configuration openclaw refuses at startup #4313 documented the hold.

Verification

  • Runtime image, through the real wrapper and OpenClaw validator (a remote test VM, image built from this branch's main):
    • runtime-image-managed-files.test.mjs now runs fix(compute): hold a gateway configuration openclaw refuses at startup #4313's beam case for an embedded and a dedicated Codex Kubernetes Gateway. The dedicated case holds gateway-config/UNAVAILABLE about 2.3 s after the container starts and logs the beam paths. The log never contains the configured value or the tool policy line.
    • Probe on main before the fix: the Dedicated Codex beam entry (enabled: false and true) was held as gateway-tool-policy/INCOMPATIBLE_RESPONSE with the tool policy line. With the fix it holds gateway-config/UNAVAILABLE at 2.7 s with "The OpenClaw Gateway did not start, and OpenClaw reports its configuration invalid (plugins.entries.beam.config.mirror.endpoint: must have required property 'endpoint'; plugins.entries.beam.config.mirror.catalogs: must have required property 'catalogs'). ...". A valid Dedicated Codex configuration still becomes ready.
  • Conformance (plugin-runtime-policy.test.mjs, for Kubernetes dedicated OpenClaw, Kubernetes dedicated Codex and Docker dedicated Codex):
    • New gateway-config cases: settings outside the policy, and a refused key next to a composed setting.
    • New gateway-tool-policy cases: a composed policy issue next to a beam issue, an invalid Codex tool exclusion, a runtime that refuses a composed key, and a report without issues.
    • The 6 new gateway-config cases fail on main and pass here.
    • The validator report fixture and the expected line moved to tests/helpers/openclaw-config-validation.mjs, which plugin-compute.test.mjs (fix(compute): hold a gateway configuration openclaw refuses at startup #4313's hold) shares.
  • Mutants: 17 of 18 killed. The survivor is equivalent: it swaps the lock and configuration checks, but a lock refusal is always a <root> issue, and a <root> issue never classifies as gateway-config.
  • Pins at 2 CPUs, 20/20 each: plugin-runtime-policy.test.mjs, plugin-compute.test.mjs, and both runtime image hold tests.
  • These lanes pass at the head on a remote test VM: static, checks-baseline-1, checks-baseline-2, images-runtime-startup and images-runtime-startup-3. The images-runtime-startup lane ran with an image built on current main, which includes build(runtime): carry openclaw#189392 startup report for invalid plugin settings #4314. Typecheck, prettier and eslint pass on the touched files, and the docs length check passes. The flow page is 1,711 words.

Risks

  • Low. The classification only chooses which held check and which log line a failed validation gets. Both outcomes hold the Gateway unready and end the deployment, so no case that held before now starts.
  • Misclassification: an invalid composed setting reported only at <root> or with an unusual message stays gateway-tool-policy, as before.
  • A different refusal on a composed setting's parent: for example, an unknown key next to agents.defaults.modelSelectionScope is now held as gateway-config, naming agents.defaults. That is the Agent's own setting.

…l policy as gateway-config

A dedicated Gateway's tool policy step validates the composed configuration
before OpenClaw starts and mapped every invalid report to the gateway-tool-policy
hold, whose log line blames the runtime image and the tool allowlist (finding
3045). When no reported issue concerns a setting the step composes, hold check
gateway-config (UNAVAILABLE) with the log line and setting paths of the
embedded Gateway's hold from #4313 instead. Policy issues, unknown roots and
validator failures keep the tool policy hold.
…assification

Drop the single-quoted key match: OpenClaw quotes refused keys with double
quotes in both its core and plugin schema messages.
@freeqaz
freeqaz requested a review from a team as a code owner October 31, 2026 14:27
@clawsweeper

clawsweeper Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

…r-neutral module

Docker's wrapper now embeds it too; importing it from the Kubernetes provider
widened the module-boundary exception (module-policy stale-exception).
@freeqaz
freeqaz merged commit 1730b12 into main Oct 31, 2026
42 checks passed
@freeqaz
freeqaz deleted the fix-3045 branch October 31, 2026 14:40
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.

1 participant