wtfutil/wtf · error

store %v: %w

Error message

store %v: %w

What it means

StoreSecret wraps failures from client.Store(prog.runner, cred) as 'store <store>: <cause>'. The credential object was built fine, but the external store program refused or failed the write. The inner error after the store name carries the real reason.

Source

Thrown at cfg/secrets.go:190

		return errors.New("cannot store secrets: wtf.secretStore is not configured")
	}

	cred := &credentials.Credentials{
		ServerURL: secret.Service,
		Username:  secret.Username,
		Secret:    secret.Secret,
	}

	// docker-credential requires a username, but it isn't necessary for
	// all services. Use a default if a username was not set.
	if cred.Username == "" {
		cred.Username = "default"
	}

	err := client.Store(prog.runner, cred)

	if err != nil {
		return fmt.Errorf("store %v: %w", prog.store, err)
	}

	return nil
}

type program struct {
	store  string
	runner client.ProgramFunc
}

func newProgram(globalConfig *config.Config) *program {
	secretStore := globalConfig.UString("wtf.secretStore", "(none)")

	if secretStore == "(none)" {
		return nil
	}

	if secretStore == "" {

View on GitHub (pinned to bb838c1ccb)

Solutions

  1. Inspect the wrapped cause after 'store <store>:' and address it
  2. Test the store manually (e.g. `pass insert test`) with the same user/environment
  3. Unlock the keychain / ensure gpg-agent is available and the GPG key is initialized
  4. Fix filesystem permissions or disk issues on the store path
  5. Check the secretStore runner configuration points at a working, executable binary

Example fix

# before (headless, keychain locked)
wtf.secretStore.type: keychain
# after
wtf.secretStore:
  type: pass
  # pass works headlessly once GNUPGHOME + key are initialized
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure backend reachable before writing
if out, err := exec.Command(storeCmd, "ls").CombinedOutput(); err != nil {
    return fmt.Errorf("store backend unhealthy: %s: %w", out, err)
}

Try / catch

if err := cfg.StoreSecret(conf, secret); err != nil {
    if unwrapped := errors.Unwrap(err); unwrapped != nil {
        log.Printf("store write failed: %v", unwrapped) // e.g. gpg/keychain error
    }
    return err
}

Prevention

When it happens

Trigger: Writing to a pass store with no initialized GPG key; keychain denied access (locked or ACL prompt rejected); read-only or missing store directory; the runner binary exiting nonzero; store rejecting an entry with empty username (code defaults it to "default", but empty service/secret can still fail).

Common situations: Headless servers without keychain access; disk full or permissions on ~/.password-store; passphrase-protected GPG key prompting in a non-interactive terminal; SELinux/AppArmor blocking the helper binary.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/0152f211757e10d8. Report an issue: GitHub.