{"record":{"id":"5dc3f78df9f33d12","repo":"wavetermdev/waveterm","slug":"failed-to-build-shell-command-w-5dc3f7","errorCode":null,"errorMessage":"failed to build shell command: %w","messagePattern":"failed to build shell command: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/genconn/wsl-impl.go","lineNumber":45,"sourceCode":"}\n\ntype WSLProcessController struct {\n\tdistro      *wsl.Distro\n\tcmd         *wsl.WslCmd\n\tlock        *sync.Mutex\n\tonce        *sync.Once\n\tstdinPiped  bool\n\tstdoutPiped bool\n\tstderrPiped bool\n\twaitErr     error\n\tstarted     bool\n\tcmdSpec     CommandSpec\n}\n\nfunc MakeWSLProcessController(distro *wsl.Distro, cmdSpec CommandSpec) (*WSLProcessController, error) {\n\tfullCmd, err := BuildShellCommand(cmdSpec)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to build shell command: %w\", err)\n\t}\n\n\tcmd := distro.WslCommand(context.Background(), fullCmd)\n\tif cmd == nil {\n\t\treturn nil, fmt.Errorf(\"failed to create WSL command\")\n\t}\n\n\treturn &WSLProcessController{\n\t\tdistro:  distro,\n\t\tcmd:     cmd,\n\t\tlock:    &sync.Mutex{},\n\t\tonce:    &sync.Once{},\n\t\tcmdSpec: cmdSpec,\n\t}, nil\n}\n\nfunc (w *WSLProcessController) Start() error {\n\tw.lock.Lock()","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/genconn/wsl-impl.go#L27-L63","documentation":"MakeWSLProcessController renders the CommandSpec into a shell command string via BuildShellCommand before creating a wsl.Distro command. If the spec is invalid, it returns 'failed to build shell command' wrapped around the underlying error. No WSL process is ever created.","triggerScenarios":"Calling MakeWSLProcessController (directly or via MakeProcessController with a WSL distro) with a CommandSpec that BuildShellCommand rejects — invalid shell name, empty command, or malformed spec fields.","commonSituations":"Spec built from user input or config with an unsupported shell; empty Command field after trimming; spec deserialized from JSON missing required keys.","solutions":["Read the wrapped BuildShellCommand error to identify the bad spec field.","Validate CommandSpec (non-empty command, supported shell) before constructing the controller.","Correct the spec at its source (config file, caller, deserialization)."],"exampleFix":"// before\nspec := genconn.CommandSpec{} // empty\nctrl, err := genconn.MakeWSLProcessController(distro, spec) // fails\n// after\nif spec.Command == \"\" { return errors.New(\"empty command\") }\nctrl, err := genconn.MakeWSLProcessController(distro, genconn.CommandSpec{Command: \"ls -la\", Shell: \"bash\"})\nif err != nil { return err }","handlingStrategy":"validation","validationCode":"func validWSLSpec(s genconn.CommandSpec) error {\n    if s.Command == \"\" { return errors.New(\"CommandSpec.Command is empty\") }\n    if s.Shell != \"\" && s.Shell != \"bash\" && s.Shell != \"sh\" { return fmt.Errorf(\"unsupported WSL shell %q\", s.Shell) }\n    return nil\n}\nif err := validWSLSpec(spec); err != nil { return err }","typeGuard":null,"tryCatchPattern":"ctrl, err := genconn.MakeWSLProcessController(distro, spec)\nif err != nil {\n    return fmt.Errorf(\"WSL controller setup failed (inspect CommandSpec): %w\", err)\n}","preventionTips":["Validate CommandSpec before construction; reject empty commands and unknown shells at config load time.","Use a fixed allowlist of shells for WSL targets.","Unit-test BuildShellCommand with every spec shape your app generates.","Fail fast at startup by constructing controllers once and surfacing spec errors early."],"tags":["wsl","command-spec","validation"],"backgroundTag":"invalid-command-spec","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}