kopia/kopia · warning

unable to persist password

Error message

unable to persist password

What it means

OnSuccess persistently saves the connected server's password after a successful connect. This error wraps a failure of s.PersistPassword (keyring or file strategy), meaning the password could not be stored for future passwordless reconnects — the connect itself succeeded.

Solutions

  1. Unlock or initialize the OS keyring (e.g. unlock gnome-keyring/login keychain) and retry the connect
  2. Check write permissions on the directory containing the config file
  3. Select a different persistence strategy (e.g. file-based) via the passwordpersist options if keyring is unavailable
  4. Persist nothing and provide the password at each connect as a fallback
Defensive patterns

Strategy: fallback

Validate before calling

// check whether the keyring is usable before attempting persistence
if _, err := keyring.Get(service, "probe"); err != nil && !errors.Is(err, keyring.ErrNotFound) {
	log.Printf("keyring unavailable, password will not persist: %v", err)
}

Type guard

null

Prevention

When it happens

Trigger: Calling OnSuccess (directly or via connect commands) when the chosen PasswordStorage's PersistPassword fails: OS keyring locked/unavailable, file write denied, or an unsupported platform strategy.

Common situations: macOS/Linux keyring locked or no keyring daemon running; read-only or unwritable config directory; disk full; headless CI without a keyring service.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/353d5e9989d98a54. Report an issue: GitHub.

Appendix: source

Thrown at internal/passwordpersist/passwordpersist.go:43

	// PersistPassword persists a password, returns ErrUnsupported or fatal errors.
	PersistPassword(ctx context.Context, configFile, password string) error

	// DeletePassword deletes any persisted password, returns fatal errors.
	DeletePassword(ctx context.Context, configFile string) error
}

// OnSuccess is a helper that persists the given (configFile,password) if the provided err is nil
// and deletes any persisted password otherwise.
func OnSuccess(ctx context.Context, err error, s Strategy, configFile, password string) error {
	if err != nil {
		if err2 := s.DeletePassword(ctx, configFile); err2 != nil {
			log(ctx).Infof("unable to delete persistent password: %v", err2)
		}

		return err
	}

	return errors.Wrap(s.PersistPassword(ctx, configFile, password), "unable to persist password")
}

View on GitHub (pinned to 82495e54b5)