moonD4rk/HackBrowserData · error

open keychain: %w

Error message

open keychain: %w

What it means

loadKeychainRecords fails to open the macOS login keychain via keychainbreaker.Open() and wraps the cause with "open keychain: %w". This is the first step of the keychain-based retriever; nothing can proceed without an open keychain handle.

Source

Thrown at masterkey/retriever_darwin.go:61

		r.records, r.err = DecryptKeychainRecords()
	})
	if r.err != nil {
		log.Debugf("gcoredump: %v", r.err)
		return nil, nil //nolint:nilerr // intentional silent fallthrough
	}

	key, err := findStorageKey(r.records, hints.KeychainLabel)
	if err != nil {
		log.Debugf("gcoredump: %v", err)
		return nil, nil //nolint:nilerr // intentional silent fallthrough
	}
	return key, nil
}

func loadKeychainRecords(password string) ([]keychainbreaker.GenericPassword, error) {
	kc, err := keychainbreaker.Open()
	if err != nil {
		return nil, fmt.Errorf("open keychain: %w", err)
	}
	if err := kc.Unlock(keychainbreaker.WithPassword(password)); err != nil {
		return nil, fmt.Errorf("unlock keychain: %w", err)
	}
	return kc.GenericPasswords()
}

func findStorageKey(records []keychainbreaker.GenericPassword, storage string) ([]byte, error) {
	for _, rec := range records {
		if rec.Account == storage {
			return darwinParams.deriveKey(rec.Password), nil
		}
	}
	return nil, fmt.Errorf("%q: %w", storage, errStorageNotFound)
}

// KeychainPasswordRetriever unlocks login.keychain-db with the macOS login password (no root).
// Records are cached once and reused across browsers.

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Verify ~/Library/Keychains/login.keychain-db exists and is readable by the current user
  2. Open Keychain Access and repair/unlock the keychain to rule out corruption
  3. Check you are running as the user who owns the keychain, not root or another account
  4. Follow the wrapped cause (errors.Unwrap) for the specific OS-level reason

Example fix

// before
keychain := os.Getenv("HOME") + "/Library/Keychains/login.keychain-db"
// after
keychain := os.Getenv("HOME") + "/Library/Keychains/login.keychain-db"
if fi, err := os.Stat(keychain); err != nil || fi.IsDir() {
	return nil, fmt.Errorf("keychain db not available at %s", keychain)
}
Defensive patterns

Strategy: validation

Validate before calling

kcPath := filepath.Join(os.Getenv("HOME"), "Library", "Keychains", "login.keychain-db")
if _, err := os.Stat(kcPath); err != nil {
	return fmt.Errorf("keychain db missing: %w", err)
}

Type guard

func keychainExists() bool {
	_, err := os.Stat(filepath.Join(os.Getenv("HOME"), "Library/Keychains/login.keychain-db"))
	return err == nil
}

Try / catch

key, err := retriever.RetrieveKey(hints)
if err != nil && strings.HasPrefix(err.Error(), "open keychain:") {
	return nil, fmt.Errorf("cannot access login keychain: %w", err)
}

Prevention

When it happens

Trigger: Calling KeychainPasswordRetriever.RetrieveKey with a non-empty password when keychainbreaker.Open() returns an error (keychain database missing, corrupted, or unreadable).

Common situations: login.keychain-db moved or deleted, running as a different user whose keychain path doesn't exist, filesystem permission problems, or corrupted keychain after a failed macOS upgrade.

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 moonD4rk/HackBrowserData@0503d04d7a (2026-09-06). Data as JSON: /api/errors/c488a55c23dd05ac. Report an issue: GitHub.