{"record":{"id":"660dbe169063a509","repo":"wavetermdev/waveterm","slug":"error-getting-secret-q-w","errorCode":null,"errorMessage":"error getting secret %q: %w","messagePattern":"error getting secret %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshserver/wshserver.go","lineNumber":1480,"sourceCode":"\nfunc (ws *WshServer) GetTabCommand(ctx context.Context, tabId string) (*waveobj.Tab, error) {\n\ttab, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting tab: %w\", err)\n\t}\n\treturn tab, nil\n}\n\nfunc (ws *WshServer) GetAllBadgesCommand(ctx context.Context) ([]baseds.BadgeEvent, error) {\n\treturn wcore.GetAllBadges(), nil\n}\n\nfunc (ws *WshServer) GetSecretsCommand(ctx context.Context, names []string) (map[string]string, error) {\n\tresult := make(map[string]string)\n\tfor _, name := range names {\n\t\tvalue, exists, err := secretstore.GetSecret(name)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error getting secret %q: %w\", name, err)\n\t\t}\n\t\tif exists {\n\t\t\tresult[name] = value\n\t\t}\n\t}\n\treturn result, nil\n}\n\nfunc (ws *WshServer) GetSecretsNamesCommand(ctx context.Context) ([]string, error) {\n\tnames, err := secretstore.GetSecretNames()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting secret names: %w\", err)\n\t}\n\treturn names, nil\n}\n\nfunc (ws *WshServer) SetSecretsCommand(ctx context.Context, secrets map[string]*string) error {\n\tfor name, value := range secrets {","sourceCodeStart":1462,"sourceCodeEnd":1498,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshserver/wshserver.go#L1462-L1498","documentation":"GetSecretsCommand iterates the requested secret names and calls secretstore.GetSecret for each. A storage-layer failure (as opposed to 'not exists', which is normal) is wrapped as \"error getting secret %q\" naming the offending secret. Wave's secret store is backed by the OS keychain (or a Linux backend), so most failures are keychain/backend level.","triggerScenarios":"GetSecretsCommand with a name whose keychain read fails — locked OS keychain (Linux gnome-keyring/KWallet unavailable or locked, macOS Keychain denying access), backend misconfiguration, or I/O failure in the fallback storage.","commonSituations":"Running Wave over SSH or headless Linux with no secret service (no D-Bus secret provider); keychain access denied after password change; disk/permission problems on the backend file.","solutions":["Read the wrapped cause to identify the backend failure (locked keychain, missing secret service, permission).","On Linux, ensure a secret service is running (gnome-keyring via D-Bus) or configure a working GetSecretsLinuxStorageBackend backend.","Unlock the OS keychain and retry the command.","Retry only the failing name — other names in the request may still resolve."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: confirm a backend exists before reading secrets (Linux)\nif runtime.GOOS == \"linux\" {\n    if _, err := wshclient.GetSecretsLinuxStorageBackendCommand(ctx); err != nil {\n        return fmt.Errorf(\"secret store unavailable: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"secrets, err := wshclient.GetSecretsCommand(ctx, names)\nif err != nil {\n    var se *storeKeychainError // inspect via errors.As on the wrapped cause if exported\n    log.Printf(\"secret read failed: %v\", err)\n    // retry per-name to isolate the failing secret\n}","preventionTips":["Preflight the backend on Linux with GetSecretsLinuxStorageBackendCommand.","Request secrets one name at a time in critical paths so one bad key doesn't fail the batch.","Ensure the OS keychain is unlocked (e.g. unlock gnome-keyring at login) before headless automation.","Distinguish exists=false (normal) from err != nil (backend failure) when interpreting results."],"tags":["secrets","keychain","rpc"],"backgroundTag":"keychain-access-denied","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}