{"record":{"id":"e28abcc418fce432","repo":"larksuite/cli","slug":"keychain-not-initialized","errorCode":null,"errorMessage":"keychain not initialized","messagePattern":"keychain not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/keychain/keychain.go","lineNumber":20,"sourceCode":"// SPDX-License-Identifier: MIT\n\n// Package keychain provides cross-platform secure storage for secrets.\n// macOS uses the system Keychain; Linux uses AES-256-GCM encrypted files; Windows uses DPAPI + registry.\npackage keychain\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/larksuite/cli/errs\"\n)\n\nvar (\n\t// ErrNotFound is returned when the requested credential is not found.\n\tErrNotFound = errors.New(\"keychain: item not found\")\n\n\t// errNotInitialized is an internal error indicating the master key is missing or invalid.\n\terrNotInitialized = errors.New(\"keychain not initialized\")\n)\n\nconst (\n\t// LarkCliService is the unified keychain service name for all secrets.\n\t// Entries are distinguished by account key format:\n\t//   - AppSecret: \"appsecret:<appId>\"\n\t//   - Stored TAT: \"tat:v1:<sha256(appId)>\"\n\t//   - UAT:       \"<appId>:<userOpenId>\"\n\tLarkCliService = \"lark-cli\"\n)\n\n// wrapError wraps underlying keychain failures into a typed *errs.APIError\n// (exit code 1) carrying a hint for troubleshooting keychain access issues.\n// nil and ErrNotFound pass through unchanged.\nfunc wrapError(op string, err error) error {\n\tif err == nil || errors.Is(err, ErrNotFound) {\n\t\treturn err\n\t}","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/keychain/keychain.go#L2-L38","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// probe master key availability before dependent operations\nif _, err := getMasterKey(ctx); err != nil {\n    // master key missing — reconfigure with `lark-cli config init`\n}","typeGuard":"func isNotInitialized(err error) bool { return errors.Is(err, errNotInitialized) }","tryCatchPattern":"err := kc.Set(service, account, secret)\nif errors.Is(err, errNotInitialized) {\n    // surface hint: reconfigure via `lark-cli config init`\n}","preventionTips":["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"],"tags":["keychain","master-key","initialization"],"backgroundTag":"keychain-not-initialized","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}