wavetermdev/waveterm · error

secret not found: %s

Error message

secret not found: %s

What it means

After a successful GetSecretsCommand RPC, the command looks up the requested name in the returned map; if the key is absent it reports the secret does not exist. This is a normal not-found condition, not an RPC failure — the daemon responded but has no secret stored under that name.

Source

Thrown at cmd/wsh/cmd/wshcmd-secret.go:95

func secretGetRun(cmd *cobra.Command, args []string) (rtnErr error) {
	defer func() {
		sendActivity("secret", rtnErr == nil)
	}()

	name := args[0]
	if !secretNameRegex.MatchString(name) {
		return fmt.Errorf("invalid secret name: must start with a letter and contain only letters, numbers, and underscores")
	}

	resp, err := wshclient.GetSecretsCommand(RpcClient, []string{name}, &wshrpc.RpcOpts{Timeout: 2000})
	if err != nil {
		return fmt.Errorf("getting secret: %w", err)
	}

	value, ok := resp[name]
	if !ok {
		return fmt.Errorf("secret not found: %s", name)
	}

	WriteStdout("%s\n", value)
	return nil
}

func secretSetRun(cmd *cobra.Command, args []string) (rtnErr error) {
	defer func() {
		sendActivity("secret", rtnErr == nil)
	}()

	parts := strings.SplitN(args[0], "=", 2)
	if len(parts) != 2 {
		return fmt.Errorf("invalid format: expected [name]=[value]")
	}

	name := parts[0]
	value := parts[1]

View on GitHub (pinned to a4447c1563)

Solutions

  1. Run `wsh secret list` to see the exact stored names and correct the spelling/case.
  2. Set the secret first with `wsh secret set NAME=VALUE`, then get it.
  3. If you expect the secret from another machine, remember the secret store is per-machine (keyring-backed); set it locally or sync it explicitly.
  4. If the name was set via wconfig secrets files, verify the file was loaded by the daemon and the name matches the store's naming rules.

Example fix

// before
value=$(wsh secret get DB_PASS)
// after
wsh secret list   # confirm exact name
value=$(wsh secret get DB_PASSWORD)
Defensive patterns

Strategy: validation

Validate before calling

names, _ := wshclient.GetSecretsNamesCommand(RpcClient, &wshrpc.RpcOpts{Timeout: 2000})
if !slices.Contains(names, name) {
    return fmt.Errorf("secret %q does not exist; available: %v", name, names)
}

Type guard

func secretExists(resp map[string]string, name string) bool {
    _, ok := resp[name]
    return ok
}

Try / catch

value, ok := resp[name]
if !ok {
    return fmt.Errorf("secret not found: %s (run 'wsh secret list' to see stored names)", name)
}

Prevention

When it happens

Trigger: Running `wsh secret get NAME` where NAME passes the name regex and the RPC succeeds, but no secret was ever set under NAME (or it was deleted), e.g. `wsh secret get db_password` when only `dbPassword` exists.

Common situations: Typo'd or case-mismatched names (Secrets are case-sensitive); secrets set on a different machine/profile than the one queried; secret deleted via the Wave secrets UI; fresh environment where setup scripts never ran.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/1c5539ad46f36ac0. Report an issue: GitHub.