go-delve/delve · error
redirect error: %s redirected twice
Error message
redirect error: %s redirected twice
What it means
parseOneRedirect extracts stdin/stdout/stderr redirections (<, >, 2>) from the tail of a restart command line, storing each target in a [3]string. Each stream may be redirected at most once; if the same prefix appears twice (already recorded in redirs[i]), the command is rejected with 'redirect error: %s redirected twice'.
Source
Thrown at pkg/terminal/command.go:1322
break
}
}
return true, w, redirs, nil
}
func parseOneRedirect(w []string, redirs *[3]string) ([]string, bool, error) {
prefixes := []string{"<", ">", "2>"}
names := []string{"stdin", "stdout", "stderr"}
if len(w) >= 2 {
if slices.Contains(prefixes, w[len(w)-2]) {
w[len(w)-2] += w[len(w)-1]
w = w[:len(w)-1]
}
}
for i, prefix := range prefixes {
if strings.HasPrefix(w[len(w)-1], prefix) {
if redirs[i] != "" {
return nil, false, fmt.Errorf("redirect error: %s redirected twice", names[i])
}
redirs[i] = w[len(w)-1][len(prefix):]
return w[:len(w)-1], true, nil
}
}
return w, false, nil
}
func printcontextNoState(t *Term) {
state, _ := t.client.GetState()
if state == nil || state.CurrentThread == nil {
return
}
printcontext(t, state)
}
func (c *Commands) rebuild(t *Term, ctx callContext, args string) error {
if ctx.Prefix == revPrefix {View on GitHub (pinned to a23773e6c3)
Solutions
- Keep at most one redirect per stream: `restart prog > out.txt` not `> a > b`.
- Merge the two targets: pick the single file you actually want per stream.
- Remember stdin has only one '<'; stderr only one '2>' per command line.
- If you need append behavior, this parser does not support `>>`; write to a fresh file or handle appending outside Delve.
Example fix
// before restart myprog > out.log > out2.log // error: redirect error: stdout redirected twice // after restart myprog > out.log
Defensive patterns
Strategy: validation
Validate before calling
// Ensure each redirect prefix appears at most once before invoking restart
func hasDuplicateRedirects(args string) bool {
for _, p := range []string{"<", ">", "2>"} {
if strings.Count(args, p) > 1 {
return true
}
}
return false
}
// if hasDuplicateRedirects(args) { fix args first } Try / catch
if err := cmd.Execute("restart "+args); err != nil {
if strings.Contains(err.Error(), "redirected twice") {
fmt.Fprintln(os.Stderr, "each of stdin/stdout/stderr may be redirected at most once")
}
} Prevention
- Use one redirect per stream: single <, >, and 2> per restart command.
- Do not chain `> a > b`; choose a single target file.
- Remember Delve's parser is not a shell: no >>, no pipes.
- When generating restart strings in scripts, build redirects from a map keyed by stream to guarantee uniqueness.
When it happens
Trigger: `restart prog > a > b` or `restart prog < in1 < in2` or `restart prog 2> x 2> y` — the same stream prefix encountered twice in parseNewArgv's redirect-extraction loop.
Common situations: Users assume shell-like `>>` appending or chaining works and write `> file1 > file2`; scripted restart commands built programmatically concatenate two redirect specs; copy-pasting a shell command line that legitimately redirects a stream twice.
Related errors
- illegal commandline '%s'
- command not available
- unknown config parameter
- address required
- Process %d has exited with status %d
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/14686a8c1a4d9f84.
Report an issue: GitHub.