Skip to content

fix(shellenv): preserve newlines in exported env values (ambiguous redirect)#2905

Open
mikeland73 wants to merge 2 commits into
mainfrom
claude/focused-goldberg-325efn
Open

fix(shellenv): preserve newlines in exported env values (ambiguous redirect)#2905
mikeland73 wants to merge 2 commits into
mainfrom
claude/focused-goldberg-325efn

Conversation

@mikeland73

Copy link
Copy Markdown
Collaborator

Summary

Fixes #2814.

eval "$(devbox global shellenv)" printed bash: 1__bp_interactive_mode: ambiguous redirect at every prompt when the user's environment carried a multi-line PROMPT_COMMAND (e.g. the bash-preexec value some terminals set).

Root cause: exportify in internal/devbox/envvars.go escaped literal newlines in a value as \ followed by a newline. Inside a double-quoted shell string that sequence is a line continuation, which the shell deletes — joining the value's adjacent lines. A line ending in 2>&1 collapsed into the following command __bp_interactive_mode, producing 2>&1__bp_interactive_mode, which bash parses as a redirect to the file 1__bp_interactive_mode → "ambiguous redirect".

A bare newline inside double quotes is already preserved verbatim, so the escape was both unnecessary and the source of the corruption. The fix drops the backslash escape for \n; the other special characters ($, `, ", \) are still escaped.

# before (buggy):  export PC="... 2>&1\<newline>__bp_interactive_mode";  -> value: "... 2>&1__bp_interactive_mode"
# after  (fixed):  export PC="... 2>&1<newline>__bp_interactive_mode";   -> value preserves the newline

How was it tested?

  • Added TestExportifyPreservesNewlines asserting the emitted export contains a bare (not backslash-escaped) newline and preserves the multi-line value. Existing exportify tests still pass.
  • Reproduced the shell behavior directly: sourcing the previous output collapsed the two lines (... 2>&1__bp_interactive_mode); sourcing the fixed output keeps them as separate commands.
  • go build / go vet on internal/devbox are clean.

Community Contribution License

All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.

By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.


cc @proedie (issue reporter)

🤖 Generated with Claude Code

https://claude.ai/code/session_01XMi8bm4fhxGAdxSCt5YJY3


Generated by Claude Code

exportify escaped literal newlines in environment variable values as
`\<newline>`. Inside a double-quoted shell string that sequence is a line
continuation, which the shell deletes — joining the value's adjacent lines.

For a multi-command PROMPT_COMMAND (e.g. the bash-preexec value set by some
terminals), this collapsed a line ending in `2>&1` into the next command
`__bp_interactive_mode`, producing `2>&1__bp_interactive_mode` and the
`bash: 1__bp_interactive_mode: ambiguous redirect` error on every prompt.

A bare newline inside double quotes is already preserved verbatim, so simply
drop the backslash escape for `\n`. Add a regression test.

Fixes #2814

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XMi8bm4fhxGAdxSCt5YJY3
Copilot AI review requested due to automatic review settings July 6, 2026 14:07

Copilot AI 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.

Pull request overview

Fixes an issue in devbox global shellenv where multi-line environment variable values (notably PROMPT_COMMAND) were being corrupted due to incorrectly escaping literal newlines, which could trigger bash: ... ambiguous redirect errors when evaluated.

Changes:

  • Stop escaping \n in exportify so literal newlines inside double quotes are preserved verbatim (avoiding POSIX line-continuation semantics).
  • Add a regression test asserting the export output contains bare newlines and does not emit backslash-newline sequences.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
internal/devbox/envvars.go Adjusts exportify escaping rules to preserve literal newlines in exported env values.
internal/devbox/envvars_test.go Adds a regression test ensuring multi-line values are emitted without \\\n escaping and remain multi-line.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The added comment expanded the loop's scope enough for golangci-lint's
varnamelen to flag the single-letter `r`. Rename it to `char`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XMi8bm4fhxGAdxSCt5YJY3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Bash: ambiguous redirect on eval "$(devbox global shellenv)"

3 participants