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

  1. Reconfigure the CLI: run `lark-cli config init` to recreate the master key and re-store secrets
  2. Ensure the process has keychain access permissions (outside sandbox/CI restrictions)
  3. 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

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


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/e28abcc418fce432. Report an issue: GitHub.