wavetermdev/waveterm · error

deleting secret: %w

Error message

deleting secret: %w

What it means

wsh secret delete works by calling SetSecretsCommand with the secret name mapped to nil, which clears it server-side. When that RPC fails for any reason (timeout, no connection to the Wave block, server error), the CLI wraps the failure as "deleting secret: %w". It is a pass-through wrapper: the underlying cause is what matters.

Source

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

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

func secretDeleteRun(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")
	}

	secrets := map[string]*string{name: nil}
	err := wshclient.SetSecretsCommand(RpcClient, secrets, &wshrpc.RpcOpts{Timeout: 2000})
	if err != nil {
		return fmt.Errorf("deleting secret: %w", err)
	}

	WriteStdout("secret deleted: %s\n", name)
	return nil
}

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

	tabId := getTabIdFromEnv()
	if tabId == "" {
		return fmt.Errorf("no WAVETERM_TABID env var set")
	}

	wshCmd := &wshrpc.CommandCreateBlockData{
		TabId: tabId,

View on GitHub (pinned to a4447c1563)

Solutions

  1. Run the command from inside a Wave terminal block (check WAVETERM_TABID/WAVETERM_BLOCKID env vars are set) so the RPC reaches the app.
  2. Check that Wave Terminal is running and responsive; retry if the 2s RPC timed out under load.
  3. Verify the secret name with `wsh secret ls` (or equivalent) and retry with the exact name.

Example fix

// before
err := wshclient.SetSecretsCommand(RpcClient, secrets, &wshrpc.RpcOpts{Timeout: 2000})
// after
err := wshclient.SetSecretsCommand(RpcClient, secrets, &wshrpc.RpcOpts{Timeout: 2000})
if err != nil {
    return fmt.Errorf("deleting secret (is wsh attached to a running Wave block?): %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if os.Getenv("WAVETERM_BLOCKID") == "" { return errors.New("must run inside a Wave terminal block") }
if name == "" || !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`).MatchString(name) { return errors.New("invalid secret name") }

Type guard

func validSecretName(name string) bool { re := regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`); return re.MatchString(name) }

Try / catch

if err := wshclient.SetSecretsCommand(RpcClient, secrets, &wshrpc.RpcOpts{Timeout: 2000}); err != nil {
    if errors.Is(err, context.DeadlineExceeded) { /* retry once */ }
    return fmt.Errorf("deleting secret: %w", err)
}

Prevention

When it happens

Trigger: Running `wsh secret delete <name>` when the SetSecretsCommand RPC fails: not attached to a running Wave terminal block, RPC exceeds the 2000ms timeout, or the wave server rejects the delete (e.g. the secret name no longer exists or internal storage error).

Common situations: Running the command from a plain shell outside the terminal so the RPC cannot route; Wave is busy/frozen so the 2s timeout fires; typo of a nonexistent secret on backends that reject unknown keys.

Related errors


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