Skip to content

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

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

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

Conversation

@mikeland73

Copy link
Copy Markdown
Collaborator

Summary

Fixes #2814.

eval "$(devbox global shellenv)" printed bash: ...__bp_interactive_mode: ambiguous redirect at every prompt when the user's PROMPT_COMMAND was multi-line (as set up by bash-preexec / the elementary terminal integration).

Root cause: exportify (internal/devbox/envvars.go) emits each variable as export KEY="value";, escaping special characters so the value is treated literally. It escaped newlines as a backslash followed by the newline. Inside a bash double-quoted string, a backslash-newline is a line continuation that the shell removes, silently joining the two lines. So a PROMPT_COMMAND like:

__bp_precmd_invoke_cmd
dbus-send ... >/dev/null 2>&1
__bp_interactive_mode

collapsed into ... 2>&1__bp_interactive_mode, and bash parsed 2>&1__bp_interactive_mode as a redirect to the ambiguous target 1__bp_interactive_mode"ambiguous redirect".

Fix: stop escaping the newline. A literal newline inside double quotes is already preserved verbatim, so the value round-trips correctly. $, `, ", and \ are still escaped as before.

-				case '$', '`', '"', '\\', '\n':
+				case '$', '`', '"', '\\':

Demonstration of the two behaviors:

$ X="a 2>&1\<newline>b"   # backslash-newline (old): lines fused
$ echo "[$X]"
[a 2>&1b]

$ X="a 2>&1<newline>b"    # literal newline (new): preserved
$ echo "[$X]"
[a 2>&1
b]

How was it tested?

  • Added TestExportifyPreservesNewlines reproducing the issue's multi-line PROMPT_COMMAND and asserting the newline is emitted literally (never as a backslash-newline line continuation).
  • go test ./internal/devbox/ -run 'TestExportify|TestIsValidEnvName' — all pass.
  • go build ./internal/devbox/, go vet ./internal/devbox/, and gofmt -l — 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_014nhuYqHdGxzteXxH78b4sE


Generated by Claude Code

claude added 2 commits July 24, 2026 14:08
exportify escaped newlines in env values as a backslash-newline. Inside a
double-quoted bash string that is a line continuation, which the shell
removes, silently joining the two lines together. Any multi-line value —
most notably a PROMPT_COMMAND captured from bash-preexec — was corrupted:
adjacent lines fused into strings like `... 2>&1__bp_interactive_mode`,
producing a "bash: ...: ambiguous redirect" error at every prompt.

A literal newline inside double quotes is already preserved as-is, so stop
escaping it. Add a regression test covering the multi-line PROMPT_COMMAND
case from the issue.

Fixes #2814

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014nhuYqHdGxzteXxH78b4sE
The added explanatory comment widened the scope over which the single-letter
loop variable is used, tripping golangci-lint's varnamelen. Rename it to a
descriptive name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014nhuYqHdGxzteXxH78b4sE
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)"

2 participants