Skip to content

{env:} substitution breaks on Windows paths due to unescaped backslashes in JSON #35536

Closed as duplicate

Description

@licat2023

Description

{env:VAR} substitution on Windows produces InvalidEscapeCharacter errors. Environment variables like USERPROFILE expand to paths containing backslashes (e.g. C:\Users\licat). After raw string replace, sequences like \U appear in the JSON text, which the JSONC parser rejects.

Root cause: substitute() in packages/opencode/src/config/variable.ts does a plain replace() for {env:} values, unlike {file:} which wraps with JSON.stringify() to escape backslashes.

Previous report (#20640) was closed as "incorrect root cause attribution" but a corrected issue was never filed.

Plugins

No response

OpenCode version

1.17.13

Steps to reproduce

  1. On Windows, create opencode.jsonc:
    {
      "mcp": {
        "test": {
          "type": "local",
          "command": ["{env:USERPROFILE}/test.exe"]
        }
      }
    }
  2. Run opencode.
  3. Config fails to load: InvalidEscapeCharacter at line ..., column ...

Screenshot and/or share link

No response

Operating System

Windows 11

Terminal

Windows Terminal

Activity

  1. github-actions commented on Jul 6, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of an existing issue. Please check:

    If your issue is distinct from #20640 (e.g., you believe the correct fix is JSON.stringify()-based escaping rather than the slash-replacement workaround), please clarify the difference in this issue so maintainers can evaluate it separately.

  2. licat2023 commented on Jul 6, 2026

    @licat2023
    Author

    #20640 was closed by the author as "incorrect root cause attribution" (it cited a non-existent file paths.ts). The corrected issue was never filed, so the bug still exists.

    This report differs in two ways:

    1. Correct file path: the actual code is in packages/opencode/src/config/variable.ts, not paths.ts.

    2. Correct fix: {env:VAR} substitutions break on Windows (backslashes in paths produce InvalidEscapeCharacter) #20640 proposed replaceAll("\", "/") as a fix, but that is a workaround that only papers over the real problem. The right fix is to make {env:} consistent with {file:} — the latter already wraps with JSON.stringify() to escape backslashes properly. The {env:} path should do the same.

    // variable.ts - current (broken)
    text.replace(/\{env:([^}]+)\}/g, (_, v) => process.env[v] || '')
    
    // should be (like {file:} already does)
    text.replace(/\{env:([^}]+)\}/g, (_, v) => JSON.stringify(process.env[v] || '').slice(1, -1))

    The slash-replacement approach would also break cases where a literal backslash is intentional in a non-path context.

  3. licat2023 commented on Jul 6, 2026

    @licat2023
    Author

    Duplicate of #32695 — same underlying bug in variable.ts: unescaped {env:} values producing invalid JSON on Windows. #32695 has an open PR with the fix (#32786).

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions