helix-editor/helix · error · anyhow::Error

could not interpret '{}' as a Unicode character code

Error message

could not interpret '{}' as a Unicode character code

What it means

A Unicode expansion token (%u{...}, e.g. %u{25CF}) is expanded by parsing its content as hexadecimal with u32::from_str_radix(_, 16) and then char::from_u32. The error fires when the content is not valid hex or is a number that is not a valid Unicode scalar value (above 0x10FFFF, or in the surrogate range D800-DFFF).

Source

Thrown at helix-view/src/expansion.rs:123

/// `Editor`. See `expand_variable` below for more discussion of lifetimes.
pub fn expand<'a>(editor: &Editor, token: Token<'a>) -> Result<Cow<'a, str>> {
    // Note: see the `TokenKind` documentation for more details on how each branch should expand.
    match token.kind {
        TokenKind::Unquoted | TokenKind::Quoted(_) => Ok(token.content),
        TokenKind::Expansion(ExpansionKind::Variable) => {
            let var = Variable::from_name(&token.content)
                .ok_or_else(|| anyhow!("unknown variable '{}'", token.content))?;

            expand_variable(editor, var)
        }
        TokenKind::Expansion(ExpansionKind::Unicode) => {
            if let Some(ch) = u32::from_str_radix(token.content.as_ref(), 16)
                .ok()
                .and_then(char::from_u32)
            {
                Ok(Cow::Owned(ch.to_string()))
            } else {
                Err(anyhow!(
                    "could not interpret '{}' as a Unicode character code",
                    token.content
                ))
            }
        }
        TokenKind::Expand => expand_inner(editor, token.content),
        TokenKind::Expansion(ExpansionKind::Shell) => expand_shell(editor, token.content),
        TokenKind::Expansion(ExpansionKind::Register) => expand_register(editor, token.content),
        // Note: see the docs for this variant.
        TokenKind::ExpansionKind => unreachable!(
            "expansion name tokens cannot be emitted when command line validation is enabled"
        ),
    }
}

/// Expand a shell command.
pub fn expand_shell<'a>(editor: &Editor, content: Cow<'a, str>) -> Result<Cow<'a, str>> {
    use std::process::{Command, Stdio};

View on GitHub (pinned to 079a789e8c)

Solutions

  1. Use 1-6 hexadecimal digits without prefix: %u{25CF}, %u{1F600}.
  2. Keep the value within 0..=0x10FFFF and outside D800-DFFF.
  3. If you literally want text like "%u{...}" in output, escape the percent as %%u{...}.

Example fix

# before
 :echo %u{U+25CF}

# after
 :echo %u{25CF}
Defensive patterns

Strategy: validation

Validate before calling

fn valid_unicode_expansion(hex: &str) -> bool {
    u32::from_str_radix(hex, 16).ok().and_then(char::from_u32).is_some()
}

if !valid_unicode_expansion(content) {
    return Err(anyhow!("'{content}' is not a hex Unicode scalar (max 10FFFF, no surrogates)"));
}

Type guard

fn parse_codepoint(hex: &str) -> Option<char> {
    u32::from_str_radix(hex, 16).ok().and_then(char::from_u32)
}

Try / catch

match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
    Some(ch) => out.push(ch),
    None => return Err(anyhow!("invalid Unicode codepoint '{hex}'")),
}

Prevention

When it happens

Trigger: Writing %u{zzzz} (non-hex digits), %u{110000} (beyond the scalar range), or %u{D800} (unpaired surrogate); accidentally including the U+ prefix or spaces, e.g. %u{U+25CF}.

Common situations: Copy-pasting codepoints formatted as U+25CF from unicode.org or char maps; miscounting digits; assuming surrogate halves are addressable like in UTF-16.

Related errors


AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16). Data as JSON: /api/errors/59278e3aa1939a17. Report an issue: GitHub.