{"record":{"id":"de11a0a77a1f6493","repo":"wavetermdev/waveterm","slug":"must-provide-an-appid-to-writeappsecretbindingscom","errorCode":null,"errorMessage":"must provide an appId to WriteAppSecretBindingsCommand","messagePattern":"must provide an appId to WriteAppSecretBindingsCommand","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshserver/wshserver.go","lineNumber":1124,"sourceCode":"}\n\nfunc (ws *WshServer) DeleteAppFileCommand(ctx context.Context, data wshrpc.CommandDeleteAppFileData) error {\n\tif data.AppId == \"\" {\n\t\treturn fmt.Errorf(\"must provide an appId to DeleteAppFileCommand\")\n\t}\n\treturn waveappstore.DeleteAppFile(data.AppId, data.FileName)\n}\n\nfunc (ws *WshServer) RenameAppFileCommand(ctx context.Context, data wshrpc.CommandRenameAppFileData) error {\n\tif data.AppId == \"\" {\n\t\treturn fmt.Errorf(\"must provide an appId to RenameAppFileCommand\")\n\t}\n\treturn waveappstore.RenameAppFile(data.AppId, data.FromFileName, data.ToFileName)\n}\n\nfunc (ws *WshServer) WriteAppSecretBindingsCommand(ctx context.Context, data wshrpc.CommandWriteAppSecretBindingsData) error {\n\tif data.AppId == \"\" {\n\t\treturn fmt.Errorf(\"must provide an appId to WriteAppSecretBindingsCommand\")\n\t}\n\treturn waveappstore.WriteAppSecretBindings(data.AppId, data.Bindings)\n}\n\nfunc (ws *WshServer) DeleteBuilderCommand(ctx context.Context, builderId string) error {\n\tif builderId == \"\" {\n\t\treturn fmt.Errorf(\"must provide a builderId to DeleteBuilderCommand\")\n\t}\n\tbuildercontroller.DeleteController(builderId)\n\treturn nil\n}\n\nfunc (ws *WshServer) StartBuilderCommand(ctx context.Context, data wshrpc.CommandStartBuilderData) error {\n\tif data.BuilderId == \"\" {\n\t\treturn fmt.Errorf(\"must provide a builderId to StartBuilderCommand\")\n\t}\n\tbc := buildercontroller.GetOrCreateController(data.BuilderId)\n\trtInfo := wstore.GetRTInfo(waveobj.MakeORef(\"builder\", data.BuilderId))","sourceCodeStart":1106,"sourceCodeEnd":1142,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshserver/wshserver.go#L1106-L1142","documentation":"WriteAppSecretBindingsCommand persists secret bindings for an app in the wave app store, but only if the request identifies the app. The server checks data.AppId and rejects empty values before calling waveappstore.WriteAppSecretBindings. This prevents writing bindings with no owning app.","triggerScenarios":"Invoking the WriteAppSecretBindings RPC with CommandWriteAppSecretBindingsData whose AppId is \"\" — typically because the caller never set it or derived it from an empty/failed lookup.","commonSituations":"UI flows where the app was deleted or not yet created before bindings were saved; hand-written wsh clients calling the RPC for automation; copying example code that left AppId blank.","solutions":["Set AppId in CommandWriteAppSecretBindingsData from the actual app's OID before the call","Ensure the app creation flow completed and returned an appId before binding secrets","Check any helper that resolves appId from context for silent empty returns"],"exampleFix":"// before\n_, err := client.WriteAppSecretBindingsCommand(ctx, wshrpc.CommandWriteAppSecretBindingsData{Bindings: b})\n// after\nif appId == \"\" { return fmt.Errorf(\"no appId\") }\n_, err := client.WriteAppSecretBindingsCommand(ctx, wshrpc.CommandWriteAppSecretBindingsData{AppId: appId, Bindings: b})","handlingStrategy":"validation","validationCode":"if data.AppId == \"\" {\n    return fmt.Errorf(\"cannot write secret bindings: AppId is empty\")\n}\nerr := client.WriteAppSecretBindingsCommand(ctx, data)","typeGuard":"func hasAppId(data wshrpc.CommandWriteAppSecretBindingsData) bool {\n    return data.AppId != \"\"\n}","tryCatchPattern":"if err := client.WriteAppSecretBindingsCommand(ctx, data); err != nil {\n    if strings.Contains(err.Error(), \"must provide an appId\") {\n        // resolve appId from app context and retry\n    }\n    return err\n}","preventionTips":["Complete app creation before binding secrets","Resolve AppId from a single source of truth (app OID), never freeform","Unit-test RPC wrappers with empty-field cases"],"tags":["rpc","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}