larksuite/cli · error
keychain not initialized
Error message
keychain not initialized
What it means
errNotInitialized is an internal error meaning the keychain master key is missing or invalid — the storage backend exists but the CLI's wrapping key entry was never created or was cleaned up. wrapError detects it via errors.Is and swaps in a specific hint about the master key and reconfiguring via `lark-cli config init`; on darwin, getMasterKey returns it when the master-key entry is absent and creation is not allowed (e.g. during a Get).
Source
Thrown at internal/keychain/keychain.go:20
// SPDX-License-Identifier: MIT
// Package keychain provides cross-platform secure storage for secrets.
// macOS uses the system Keychain; Linux uses AES-256-GCM encrypted files; Windows uses DPAPI + registry.
package keychain
import (
"errors"
"fmt"
"github.com/larksuite/cli/errs"
)
var (
// ErrNotFound is returned when the requested credential is not found.
ErrNotFound = errors.New("keychain: item not found")
// errNotInitialized is an internal error indicating the master key is missing or invalid.
errNotInitialized = errors.New("keychain not initialized")
)
const (
// LarkCliService is the unified keychain service name for all secrets.
// Entries are distinguished by account key format:
// - AppSecret: "appsecret:<appId>"
// - Stored TAT: "tat:v1:<sha256(appId)>"
// - UAT: "<appId>:<userOpenId>"
LarkCliService = "lark-cli"
)
// wrapError wraps underlying keychain failures into a typed *errs.APIError
// (exit code 1) carrying a hint for troubleshooting keychain access issues.
// nil and ErrNotFound pass through unchanged.
func wrapError(op string, err error) error {
if err == nil || errors.Is(err, ErrNotFound) {
return err
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Reconfigure the CLI: run `lark-cli config init` to recreate the master key and re-store secrets
- Ensure the process has keychain access permissions (outside sandbox/CI restrictions)
- If in CI, provision the keychain state or use the file-master-key downgrade path explicitly
Defensive patterns
Strategy: try-catch
Validate before calling
// probe master key availability before dependent operations
if _, err := getMasterKey(ctx); err != nil {
// master key missing — reconfigure with `lark-cli config init`
} Type guard
func isNotInitialized(err error) bool { return errors.Is(err, errNotInitialized) } Try / catch
err := kc.Set(service, account, secret)
if errors.Is(err, errNotInitialized) {
// surface hint: reconfigure via `lark-cli config init`
} Prevention
- Avoid wiping keychain items owned by lark-cli
- Re-run `lark-cli config init` after switching machines or cleaning keychains
- Grant CI/sandbox processes keychain access or use the file downgrade path
- Follow the hint text emitted by wrapError for this error
When it happens
Trigger: Calling keychain Get/Set where the master key entry is absent and cannot be created (keychain_darwin.go:101), or DowngradeMasterKeyToFile/getFileMasterKey operating on an uninitialized store.
Common situations: Running in a sandbox/CI where the keychain entry was cleaned up between runs; deleting keychain items via Keychain Access; switching machines without migrating the master key.
Related errors
- keychain: item not found
- keychain access blocked
- keychain unavailable: %w hint: use file: reference in config
- appSecret keychain key %q does not match appId %q (expected
- dpapi protect failed: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/e28abcc418fce432.
Report an issue: GitHub.