jdx/mise · error

incomplete Go string escape

Error message

incomplete Go string escape

What it means

`escape_character` reads a fixed number of digits (for octal, hex \x, \u, or \U escapes) from the string's character iterator. If fewer than the required digits remain before the string ends, the escape is truncated and this error is thrown.

Source

Thrown at src/task/workspace/go.rs:257

                    );
                }
                decoded_character(&digits, 8)?
            }
            _ => bail!("unsupported Go string escape \\{escape}"),
        };
        unescaped.push(escaped);
    }
    Ok(unescaped)
}

fn escape_character(
    characters: &mut std::str::Chars<'_>,
    length: usize,
    radix: u32,
) -> Result<char> {
    let digits = characters.take(length).collect::<String>();
    if digits.chars().count() != length {
        bail!("incomplete Go string escape");
    }
    decoded_character(&digits, radix)
}

fn decoded_character(digits: &str, radix: u32) -> Result<char> {
    let value = u32::from_str_radix(digits, radix)
        .wrap_err_with(|| format!("invalid Go string escape {digits:?}"))?;
    char::from_u32(value).ok_or_else(|| eyre::eyre!("invalid Go character escape {digits:?}"))
}

fn strip_comment(line: &str) -> &str {
    let mut quote = None;
    let mut escaped = false;
    for (index, character) in line.char_indices() {
        match quote {
            Some('"') if escaped => escaped = false,
            Some('"') if character == '\\' => escaped = true,
            Some(delimiter) if character == delimiter => quote = None,

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Complete the escape with the required number of digits (2 for \x/octal-count, 4 for \u, 8 for \U)
  2. Shorten to the compact \x form if the codepoint fits, reducing digit-count mistakes
  3. Simplify to a plain character or a named escape like \n instead of a numeric one

Example fix

// before
module "ex\x4mple"
// after
module "ex\x4dmple"
Defensive patterns

Strategy: validation

Validate before calling

fn validate_escape_digit_counts(inner: &str) -> Result<()> {
    let need = |c: char| match c { 'x' => 2, 'u' => 4, 'U' => 8, _ => 0 };
    let mut chars = inner.chars().peekable();
    while let Some(c) = chars.next() {
        if c == '\\' {
            if let Some(n) = chars.peek().copied().map(need) {
                anyhow::ensure!(chars.as_str().chars().take(n).count() == n, "incomplete escape at end of string");
            }
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: An interpreted Go string ending mid-escape, e.g. `\x4` (needs 2 hex digits), `\u00` (needs 4), `\U0000` (needs 8), or `\40` octal with digits cut off by the closing quote.

Common situations: Manually typing hex/unicode escapes and losing digits; a truncating editor or copy-paste clipping the tail of the string; templating that dropped trailing characters.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/001c2681169f2c4f. Report an issue: GitHub.