golang/go · error

unterminated quoted argument

Error message

unterminated quoted argument

What it means

Thrown by the script parser when a single-quote opens a quoted chunk that is never closed before the end of the line. The parser scans char by char; on reaching i >= len(line) while still inside a quoted region (quoted == true) it returns this error. Single quotes are the only quoting mechanism in the script grammar and '' inside doubles to embed a literal quote.

Source

Thrown at src/cmd/internal/script/engine.go:418

	}

	for i := 0; ; i++ {
		if !quoted && (i >= len(line) || strings.ContainsRune(argSepChars, rune(line[i]))) {
			// Found arg-separating space.
			if start >= 0 {
				rawArg = append(rawArg, argFragment{s: line[start:i], quoted: false})
				start = -1
			}
			if err := flushArg(); err != nil {
				return nil, err
			}
			if i >= len(line) || line[i] == '#' {
				break
			}
			continue
		}
		if i >= len(line) {
			return nil, errors.New("unterminated quoted argument")
		}
		if line[i] == '\'' {
			if !quoted {
				// starting a quoted chunk
				if start >= 0 {
					rawArg = append(rawArg, argFragment{s: line[start:i], quoted: false})
				}
				start = i + 1
				quoted = true
				continue
			}
			// 'foo''bar' means foo'bar, like in rc shell and Pascal.
			if i+1 < len(line) && line[i+1] == '\'' {
				rawArg = append(rawArg, argFragment{s: line[start:i], quoted: true})
				start = i + 1
				i++ // skip over second ' before next iteration
				continue
			}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Close every opening single quote with a matching closing quote.
  2. To embed a literal single quote, double it: `'Don''t'` yields `Don't`.
  3. If a value contains many quotes, consider an environment variable set via Setenv instead of inline quoting.

Example fix

// before
echo 'Don't communicate by sharing memory'
# -> unterminated quoted argument

// after (double the inner quote)
echo 'Don''t communicate by sharing memory'
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every opening single quote is matched.
func balancedQuotes(line string) error {
    inQuote := false
    for i := 0; i < len(line); i++ {
        if line[i] == '\'' {
            if !inQuote { inQuote = true; continue }
            if i+1 < len(line) && line[i+1] == '\'' { i++; continue } // doubled
            inQuote = false
        }
    }
    if inQuote { return errors.New("unterminated quoted argument") }
    return nil
}

Type guard

func isUnterminatedQuote(err error) bool {
    return err != nil && err.Error() == "unterminated quoted argument"
}

Try / catch

// Lint script files for unbalanced single quotes before running them.

Prevention

When it happens

Trigger: A script line with an odd number of single quotes, e.g. `cat 'foo`, or `echo 'Don't communicate'` (the apostrophe in Don't closes the quote early and the rest is misparsed), or a trailing unclosed argument like `cd 'some path`.

Common situations: Embedding an apostrophe in a quoted string without doubling it (the script grammar, like rc/Pascal, uses '' for a literal quote). Copy-pasting a path with a quote. A multi-line value accidentally collapsed onto one line leaving an open quote.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/34de86dc8de9745e. Report an issue: GitHub.