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

Register {name} does not support writing

Error message

Register {name} does not support writing

What it means

Registers::write refuses writes to the three read-only registers: '#' (selection indices), '.' (last inserted text), and '%' (document name). These are computed values, so assigning to them is an error rather than a silent no-op. Writing to '_' (black hole) is accepted and discards the value.

Source

Thrown at helix-view/src/register.rs:83

                &self.clipboard_provider.load(),
                self.inner.get(&name),
                match name {
                    '+' => ClipboardType::Clipboard,
                    '*' => ClipboardType::Selection,
                    _ => unreachable!(),
                },
            )),
            _ => self
                .inner
                .get(&name)
                .map(|values| RegisterValues::new(values.iter().map(Cow::from).rev())),
        }
    }

    pub fn write(&mut self, name: char, mut values: Vec<String>) -> Result<()> {
        match name {
            '_' => Ok(()),
            '#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support writing")),
            '*' | '+' => {
                self.clipboard_provider.load().set_contents(
                    &values.join(NATIVE_LINE_ENDING.as_str()),
                    match name {
                        '+' => ClipboardType::Clipboard,
                        '*' => ClipboardType::Selection,
                        _ => unreachable!(),
                    },
                )?;
                values.reverse();
                self.inner.insert(name, values);
                Ok(())
            }
            _ => {
                values.reverse();
                self.inner.insert(name, values);
                Ok(())
            }

View on GitHub (pinned to 079a789e8c)

Solutions

  1. Target a writable register: named a-z/0-9, the default '"', or clipboard '*'/'+'.
  2. To change what '%' reports, rename the document rather than writing the register.
  3. Use '_' if you intentionally want the write to be discarded (e.g. uniform code paths).

Example fix

# before
 :set-register % myfile.txt

# after
 :write myfile.txt  # rename/save changes the buffer name instead
Defensive patterns

Strategy: validation

Validate before calling

const READ_ONLY_REGISTERS: [char; 3] = ['#', '.', '%'];

fn can_write_register(name: char) -> bool {
    !READ_ONLY_REGISTERS.contains(&name)
}

Type guard

fn writable_register(name: char) -> Option<char> {
    (!matches!(name, '#' | '.' | '%')).then_some(name)
}

Try / catch

if let Err(err) = registers.write(name, values) {
    if err.to_string().contains("does not support writing") {
        editor.set_error(format!("register '{name}' is read-only (computed by the editor)"));
    } else {
        return Err(err);
    }
}

Prevention

When it happens

Trigger: Running :set-register % value, :set-register . value or :set-register # value; calling registers.write('%', vals) from code; yank/append commands aimed at one of these three names.

Common situations: Users experimenting with :set-register and picking a special register; scripts that programmatically stage text into '%' expecting it to change the filename (it cannot — use rename instead); Vim habits where some of these registers behave differently.

Related errors


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