{"record":{"id":"4a0484f8d2cc349c","repo":"larksuite/cli","slug":"keychain-item-not-found","errorCode":null,"errorMessage":"keychain: item not found","messagePattern":"keychain: item not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/keychain/keychain.go","lineNumber":17,"sourceCode":"// Copyright (c) 2026 Lark Technologies Pte. Ltd.\n// 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 {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/keychain/keychain.go#L1-L35","documentation":"keychain.ErrNotFound is returned when the requested credential (service+account entry) does not exist in the OS keychain/credential store. Get surfaces it and wrapError passes it through unchanged (it is terminal, not a hint case). Callers like the config loader treat it as 'no stored credential' — an expected, recoverable state — rather than a failure of the keychain itself.","triggerScenarios":"Calling keychain Get for a service/account (e.g. appsecret:<appId>) that was never Set, or after the entry was deleted; stubbing in tests (config_test.go stubKeychain returns it).","commonSituations":"Fresh machine or fresh user profile with no stored credentials; running `config init` never executed; credential removed by keychain cleanup or a different user account.","solutions":["Run `lark-cli config init` (or the relevant auth flow) to store the credential","Check you are running as the same OS user that stored the credential","Handle ErrNotFound explicitly in code as 'not configured' rather than a hard failure"],"exampleFix":"// before\nsecret, err := kc.Get(service, account)\nif err != nil { return err }\n// after\nsecret, err := kc.Get(service, account)\nif errors.Is(err, keychain.ErrNotFound) { return nil // prompt user to configure }","handlingStrategy":"type-guard","validationCode":"// check config state before touching the keychain\nif _, err := kc.Get(service, account); errors.Is(err, keychain.ErrNotFound) {\n    // credential absent — run `lark-cli config init`\n}","typeGuard":"func isCredentialMissing(err error) bool { return errors.Is(err, keychain.ErrNotFound) }","tryCatchPattern":"secret, err := kc.Get(service, account)\nswitch {\ncase errors.Is(err, keychain.ErrNotFound):\n    // prompt user to configure; not a keychain failure\ncase err != nil:\n    // real keychain failure\n}","preventionTips":["Run `lark-cli config init` on new machines/profiles","Treat ErrNotFound as expected 'not configured' state in code","Store credentials under the same OS user that consumes them","Check keychain entries before deleting via system tools"],"tags":["keychain","credentials","not-found"],"backgroundTag":"credential-not-found","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"}