helix-editor/helix · error · anyhow::Error
Failed to push to register
Error message
Failed to push to register {name}: clipboard does not match register contents What it means
Pushing to '*' or '+' must append to the live system clipboard, so the code first verifies the current clipboard contents still equal what the register last stored (contents_are_saved). If another program (or a clipboard manager) changed the clipboard in between, appending would silently drop that foreign content, so it bails with "clipboard does not match register contents" instead of corrupting state.
Solutions
- Overwrite instead of append: a plain write to '*'/'+ resets the register's view of the clipboard and clears the mismatch.
- Accumulate in a named register (a-z) and copy the final result to '+' once, avoiding interleaved OS clipboard use.
- Disable or configure clipboard managers that rewrite contents (trailing-newline trimming is a classic cause).
Example fix
# before
yank to '+', copy elsewhere, push to '+' again # mismatch error
# after
yank to 'a' repeatedly, then :set-register + "#{a:content}" # single final copy Defensive patterns
Strategy: fallback
Validate before calling
fn clipboard_in_sync(registers: &Registers, name: char, provider: &ClipboardProvider) -> bool {
let Ok(current) = provider.load().get_contents(&match name { '+' => ClipboardType::Clipboard, _ => ClipboardType::Selection }) else { return false };
registers.read(name, editor)
.map(|vals| contents_are_saved(&vals.collect::<Vec<_>>(), ¤t))
.unwrap_or(false)
} Try / catch
match registers.push('+', value) {
Err(err) if err.to_string().contains("clipboard does not match") => {
// foreign clipboard change: overwrite instead of append to resync
registers.write('+', vec![value])?;
}
other => other?,
} Prevention
- Prefer a single write over repeated pushes to '*'/'+'.
- Accumulate in named registers; copy to the clipboard once at the end.
- Disable clipboard managers that trim newlines or rewrite contents between yanks.
When it happens
Trigger: Yank/push to the '+' register, copy something in any other application (or let a clipboard manager mutate/normalize it), then push again to the same register; also triggered by clipboard managers that trim trailing newlines or re-encode text.
Common situations: Accumulating multiple selections into the clipboard across a few minutes while using the OS normally; Linux clipboard managers (clipit, klipper) or tmux/Wayland synchronization altering contents; whitespace/newline normalization by desktop environments between pushes.
Related errors
- Register does not support pushing
- Register does not support writing
- can only set a split once of a specific type
- Command not provided
- --config must specify a path to read
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/357e3a68813f75d2.
Report an issue: GitHub.
Appendix: source
Thrown at helix-view/src/register.rs:122
pub fn push(&mut self, name: char, mut value: String) -> Result<()> {
match name {
'_' => Ok(()),
'#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support pushing")),
'*' | '+' => {
let clipboard_type = match name {
'+' => ClipboardType::Clipboard,
'*' => ClipboardType::Selection,
_ => unreachable!(),
};
let contents = self
.clipboard_provider
.load()
.get_contents(&clipboard_type)?;
let saved_values = self.inner.entry(name).or_default();
if !contents_are_saved(saved_values, &contents) {
anyhow::bail!("Failed to push to register {name}: clipboard does not match register contents");
}
saved_values.push(value.clone());
if !contents.is_empty() {
value.push_str(NATIVE_LINE_ENDING.as_str());
}
value.push_str(&contents);
self.clipboard_provider
.load()
.set_contents(&value, clipboard_type)?;
Ok(())
}
_ => {
self.inner.entry(name).or_default().push(value);
Ok(())
}
}View on GitHub (pinned to 079a789e8c)