Skip to content

fix(core): escape env config values that break parsing - #55915

Merged
rekram1-node merged 5 commits into
devfrom
config-env-cost
Oct 16, 2026
Merged

rekram1-node merged 5 commits into
devfrom
config-env-cost

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Refs #42856. Previously reported on V1 in #20640, #32695, #35536 and #43691, none of which were fixed.

{env:VAR} values are pasted into the config text before it is parsed. A value containing a backslash or a quote, such as a Windows path, made the JSON invalid, and the whole config file was rejected with only a warning in the log.

Values are still substituted raw first. Only if that produces invalid JSON are they substituted again with escaping, the same escaping {file:} uses. Configs that load today are unchanged, including unquoted references and values someone already escaped by hand (e.g. C:\\Users).

Also restores the V1 "Variables" docs section ({env:} and {file:}) to the V2 config page, adapted to V2 config keys.

Verified with an extended substitution test (Windows path with a quote, plus an unquoted boolean reference) and bun run check.

@opencode-agent opencode-agent Bot 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.

The change looks sound to me. I checked the {env:} substitution directly on the base and with this PR. With a value of C:\new\tools"x, the base produces invalid JSONC (the whole document gets rejected). With this PR it parses to exactly the env value, and unquoted {env:PORT} numbers still work. The new or changed config and provider tests pass here and fail on the base code. The core and schema type checks pass. I couldn't run the CLI end-to-end in this sandbox: bun fails to load react/jsx-dev-runtime on both checkouts.

I checked every caller of ConfigVariable.substitute (config files, OPENCODE_CONFIG_CONTENT, managed preferences, wellknown remote config). All of them feed it JSON or JSONC text, so JSON-escaping is correct everywhere. The wellknown path also gains from it: credential keys containing quotes or backslashes no longer break the remote config.

Public API (backwards compatible):

  • Model config cost.input / cost.output: required → optional, with matching changes in the OpenAPI spec and the generated client Config.Model.Cost types. Existing configs still validate.
  • {env:VAR} values are now JSON-escaped. Quoted and unquoted number/boolean uses are unchanged. Pasting raw JSON objects through an unquoted {env:} (undocumented) stops working.
  • An explicit cost without cache now keeps the catalog's cache prices instead of zeroing them.

No blocking concerns.

Fixes #51637
Related: #42856

@rekram1-node rekram1-node changed the title fix(core): escape env config values and default omitted model costs fix(core): escape quoted env config values Oct 16, 2026
@rekram1-node rekram1-node changed the title fix(core): escape quoted env config values fix(core): recover from quoted env values and partial model costs Oct 16, 2026
@rekram1-node rekram1-node changed the title fix(core): recover from quoted env values and partial model costs fix(core): escape quoted env config values Oct 16, 2026
@rekram1-node rekram1-node changed the title fix(core): escape quoted env config values fix(core): escape env config values that break parsing Oct 16, 2026
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