micro-editor/micro · warning

Cannot save scratch buffer

Error message

Cannot save scratch buffer

What it means

Returned by (*Buffer).saveToFile (internal/buffer/save.go:238) when b.Type.Scratch is true. Scratch buffers (help pages, command output like plugin-search results, and other internal ephemeral panes) have no backing file identity; refusing the save keeps them from corrupting disk state. Like [17] it guards every save variant including SaveAs.

Source

Thrown at internal/buffer/save.go:238

func (b *Buffer) SaveAs(filename string) error {
	return b.saveToFile(filename, false, false)
}

func (b *Buffer) SaveWithSudo() error {
	return b.SaveAsWithSudo(b.Path)
}

func (b *Buffer) SaveAsWithSudo(filename string) error {
	return b.saveToFile(filename, true, false)
}

func (b *Buffer) saveToFile(filename string, withSudo bool, autoSave bool) error {
	var err error
	if b.Type.Readonly {
		return errors.New("Cannot save readonly buffer")
	}
	if b.Type.Scratch {
		return errors.New("Cannot save scratch buffer")
	}

	if withSudo {
		_, err := exec.LookPath(config.GlobalSettings["sucmd"].(string))
		if err != nil {
			return err
		}
	}

	if !autoSave && b.Settings["rmtrailingws"].(bool) {
		for i, l := range b.lines {
			leftover := util.CharacterCount(bytes.TrimRightFunc(l.data, unicode.IsSpace))

			linelen := util.CharacterCount(l.data)
			b.Remove(Loc{leftover, i}, Loc{linelen, i})
		}

		b.RelocateCursors()

View on GitHub (pinned to 1c8b82b32e)

Solutions

  1. Move focus back to a file buffer (Ctrl-w / tab switching) before saving
  2. To persist scratch content: copy it into a new file buffer (:open /tmp/notes, paste, save)
  3. Plugin authors: use a non-scratch type if persistence is intended, or wire save to serialize the content yourself

Example fix

// before
// active pane: Help keybindings
Ctrl-s  ->  Cannot save scratch buffer

// after
// copy text (Ctrl-a Ctrl-c), then
:open ~/notes.md   // paste (Ctrl-v) and Ctrl-s
Defensive patterns

Strategy: validation

Validate before calling

// Filter global save bindings by buffer type
if h.Buf.Type.Scratch || h.Buf.Type.Readonly {
    InfoBar.Message("scratch pane has no file — copy to a new buffer to persist")
    return
}
h.Save()

Try / catch

if err := h.Buf.Save(); err != nil {
    switch err.Error() {
    case "Cannot save scratch buffer":
        InfoBar.Error("scratch buffer: select-all, copy, then :open <file> and paste")
        return
    case "Cannot save readonly buffer":
        InfoBar.Error(err)
        return
    }
    return err
}

Prevention

When it happens

Trigger: Running :w, Ctrl-s, or :save while a help page or a scratch command-output buffer (e.g. the plugin manager listing) is the active pane.

Common situations: Split layout where a help/scratch pane keeps focus and the user reflexively saves; plugins that map a global save key and don't filter buffer types.

Related errors


AI-assisted analysis of micro-editor/micro@1c8b82b32e (2026-08-15). Data as JSON: /api/errors/89ff4d53362d914b. Report an issue: GitHub.