cayleygraph/cayley · warning

could not open %q to append history: %v

Error message

could not open %q to append history: %v

What it means

This error is returned by the REPL's persist helper when it cannot open the history file for appending. os.OpenFile with O_RDWR|O_APPEND|O_CREATE failed — typically due to filesystem permissions, a missing parent directory, or the path being a directory. The REPL then reports the path and the underlying OS error so history cannot be saved.

Source

Thrown at internal/repl/repl.go:275

			os.Exit(1)
		}

		os.Exit(0)
	}()

	f, err := os.Open(path)
	if err != nil {
		return term, err
	}
	defer f.Close()
	_, err = term.ReadHistory(f)
	return term, err
}

func persist(term *liner.State, path string) error {
	f, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		return fmt.Errorf("could not open %q to append history: %v", path, err)
	}
	defer f.Close()
	_, err = term.WriteHistory(f)
	if err != nil {
		return fmt.Errorf("could not write history to %q: %v", path, err)
	}
	return term.Close()
}

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Check the underlying OS error (%v) — fix permissions with chmod/chown on the file or its parent directory.
  2. Create the parent directory of the history file before starting the REPL (mkdir -p).
  3. Pass a writable file path via the history flag/option, e.g. --history /tmp/cayley_history.
  4. If HOME is unset in the environment, set HOME to a writable directory or give an explicit history path.

Example fix

// before
cayley repl --history ~/nonexistent-dir/history
// after
mkdir -p ~/cayley && cayley repl --history ~/cayley/history
Defensive patterns

Strategy: try-catch

Validate before calling

dir := filepath.Dir(historyPath)
if _, err := os.Stat(dir); os.IsNotExist(err) {
	os.MkdirAll(dir, 0o755)
}
if f, err := os.OpenFile(historyPath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0o666); err != nil {
	return err
} else {
	f.Close()
}

Try / catch

if err := repl.Repl(ctx, h, lang, timeout); err != nil {
	var pe *fs.PathError
	if errors.As(err, &pe) {
		log.Printf("history file unavailable (%v); continuing without history", pe)
	} else {
		return err
	}
}

Prevention

When it happens

Trigger: Calling persist (from Repl at exit, or directly) with a history path whose parent directory does not exist, is not writable by the current user (e.g. $HOME unset or read-only, custom --history path under a protected directory), or where the path is an existing directory.

Common situations: Running in a container/CI where HOME is unset so the default history path is invalid; a read-only home directory or NFS mount; passing --history /some/dir (a directory) instead of a file path; a disk-quota or permission issue after switching users.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/858231cd19eb7f65. Report an issue: GitHub.