wavetermdev/waveterm · error
failed to get secret %q: %w
Error message
failed to get secret %q: %w
What it means
For each bound secret, BuildAppSecretEnv calls secretstore.GetSecret(boundSecretName). If the secret store itself returns an error (as opposed to a clean 'not exists'), the lookup is aborted and wrapped as 'failed to get secret %q'. This signals a malfunction of the secret store backend, not a missing binding.
Source
Thrown at pkg/waveappstore/waveappstore.go:828
bindings = make(map[string]string)
}
secretEnv := make(map[string]string)
for secretName, secretMeta := range manifest.Secrets {
boundSecretName, hasBinding := bindings[secretName]
if !secretMeta.Optional && !hasBinding {
return nil, fmt.Errorf("required secret %q is not bound", secretName)
}
if !hasBinding {
continue
}
secretValue, exists, err := secretstore.GetSecret(boundSecretName)
if err != nil {
return nil, fmt.Errorf("failed to get secret %q: %w", boundSecretName, err)
}
if !exists {
if !secretMeta.Optional {
return nil, fmt.Errorf("required secret %q is bound to %q which does not exist in secret store", secretName, boundSecretName)
}
continue
}
secretEnv[secretName] = secretValue
}
return secretEnv, nil
}
View on GitHub (pinned to a4447c1563)
Solutions
- Inspect the wrapped %w error to identify the backend failure (access denied vs corruption)
- Unlock the OS keychain / start the secret service (gnome-keyring, keychain daemon) and retry
- Verify the bound key name is a valid store key (no stray whitespace or wrong key)
- Test the key directly with secretstore.GetSecret to reproduce outside BuildAppSecretEnv
- If the store file is corrupted, restore it from backup or re-enter the secrets
Example fix
// before
val, exists, err := secretstore.GetSecret(" myapp/api-key") // key has leading space -> backend error
// after
key := strings.TrimSpace("myapp/api-key")
val, exists, err := secretstore.GetSecret(key)
if err != nil { return fmt.Errorf("secret store unavailable: %w", err) } Defensive patterns
Strategy: try-catch
Validate before calling
for _, bound := range bindings {
if _, _, err := secretstore.GetSecret(strings.TrimSpace(bound)); err != nil {
return fmt.Errorf("secret store precheck failed for %q: %w", bound, err)
}
} Type guard
func secretStoreHealthy(keys []string) bool {
for _, k := range keys {
if _, _, err := secretstore.GetSecret(k); err != nil { return false }
}
return true
} Try / catch
env, err := waveappstore.BuildAppSecretEnv(appId, manifest, bindings)
if err != nil && strings.Contains(err.Error(), "failed to get secret") {
return fmt.Errorf("secret store backend failure, check keychain/daemon: %w", err)
} Prevention
- Ensure the OS keychain/secret service is running and unlocked before launching apps
- Trim and normalize bound key names before storing them
- Test GetSecret on the key directly when debugging
- Avoid editing the secret store file by hand
When it happens
Trigger: secretstore.GetSecret returns a non-nil error: corrupted/locked store backend, keychain access denied (OS keychain prompt rejected), store file unreadable, or backend initialization failure while resolving the bound key name.
Common situations: OS keychain is locked or denied access to the process (Linux secret service not running, macOS Keychain prompt denied, Windows Credential Manager issue); the secret store file was manually edited and corrupted; running headless where the keychain daemon is unavailable.
Related errors
- failed to read secret bindings (ERR-SECRET): %w
- failed to build secret environment (ERR-SECRET): %w
- required secret %q is not bound
- required secret %q is bound to %q which does not exist in se
- error getting secret %q: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f62e7f9f6b116a52.
Report an issue: GitHub.