{"record":{"id":"0016574448dd1795","repo":"wavetermdev/waveterm","slug":"no-waveterm-tabid-env-var-set-001657","errorCode":null,"errorMessage":"no WAVETERM_TABID env var set","messagePattern":"no WAVETERM_TABID env var set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/wsh/cmd/wshcmd-secret.go","lineNumber":181,"sourceCode":"\n\tsecrets := map[string]*string{name: nil}\n\terr := wshclient.SetSecretsCommand(RpcClient, secrets, &wshrpc.RpcOpts{Timeout: 2000})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"deleting secret: %w\", err)\n\t}\n\n\tWriteStdout(\"secret deleted: %s\\n\", name)\n\treturn nil\n}\n\nfunc secretUiRun(cmd *cobra.Command, args []string) (rtnErr error) {\n\tdefer func() {\n\t\tsendActivity(\"secret\", rtnErr == nil)\n\t}()\n\n\ttabId := getTabIdFromEnv()\n\tif tabId == \"\" {\n\t\treturn fmt.Errorf(\"no WAVETERM_TABID env var set\")\n\t}\n\n\twshCmd := &wshrpc.CommandCreateBlockData{\n\t\tTabId: tabId,\n\t\tBlockDef: &waveobj.BlockDef{\n\t\t\tMeta: map[string]interface{}{\n\t\t\t\twaveobj.MetaKey_View: \"waveconfig\",\n\t\t\t\twaveobj.MetaKey_File: \"secrets\",\n\t\t\t},\n\t\t},\n\t\tMagnified: secretUiMagnified,\n\t\tFocused:   true,\n\t}\n\n\t_, err := wshclient.CreateBlockCommand(RpcClient, *wshCmd, &wshrpc.RpcOpts{Timeout: 2000})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"opening secrets UI: %w\", err)\n\t}","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-secret.go#L163-L199","documentation":"`wsh secret ui` opens the secrets UI block in the Wave terminal via RPC, which needs the current tab id. The CLI derives it from the WAVETERM_TABID environment variable injected by Wave into every terminal block. If that variable is absent, wsh has no way to know where to create the block, so it fails before making any RPC.","triggerScenarios":"Running `wsh secret ui` in an environment where WAVETERM_TABID is unset: a plain OS shell (ssh session, CI runner, bare terminal), or inside a Wave block where the env var was stripped (e.g. via `env -i`, sudo, or a nested shell that sanitized the environment).","commonSituations":"SSH-ing into a remote host and running wsh there; scripts that sanitize env before exec; older Wave versions or plain terminals that don't inject WAVETERM_TABID.","solutions":["Run `wsh secret ui` from inside a Wave Terminal block so WAVETERM_TABID is injected.","Check `echo $WAVETERM_TABID`; if empty, re-open a Wave terminal block instead of a plain terminal.","If using sudo/env -i, preserve the var: `sudo --preserve-env=WAVETERM_TABID wsh secret ui`.","On remote hosts, use `wsh setenv`/conn-related tooling or run the command locally in Wave instead."],"exampleFix":"// before (plain shell)\n$ wsh secret ui\n// after (run inside a Wave terminal block where the var is present)\n$ echo $WAVETERM_TABID   # e.g. 8f2c...\n$ wsh secret ui","handlingStrategy":"validation","validationCode":"if os.Getenv(\"WAVETERM_TABID\") == \"\" {\n    return errors.New(\"run from inside a Wave terminal block (WAVETERM_TABID not set)\")\n}","typeGuard":null,"tryCatchPattern":"if err := run(); err != nil {\n    if strings.Contains(err.Error(), \"WAVETERM_TABID\") {\n        fmt.Fprintln(os.Stderr, \"Hint: open a Wave terminal block and retry\")\n    }\n}","preventionTips":["Run wsh commands inside Wave Terminal blocks, not plain terminals or CI shells.","Avoid sudo/env -i wrappers that strip WAVETERM_* variables; use --preserve-env if needed.","Check `env | grep WAVETERM` before scripting against wsh."],"tags":["cli","environment","wave-terminal","missing-env-var"],"backgroundTag":"missing-env-var","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}