hashicorp/nomad · error
writer ui: unsupported Ui type: %T
Error message
writer ui: unsupported Ui type: %T
What it means
NewWriterUI wraps an existing mitchellh/cli.Ui so command output can be redirected to custom writers. It only understands *cli.BasicUi and *cli.ColoredUi; anything else falls into the type-switch default and this error is returned. It exists to fail fast when an unsupported Ui implementation is passed instead of silently mis-routing output.
Source
Thrown at command/ui/writer_ui.go:62
}
switch u := ui.(type) {
case *cli.MockUi:
wUI.reader = u.InputReader
wUI.writer = u.OutputWriter
wUI.errorWriter = u.ErrorWriter
wUI.baseUi = u
done = true
case *cli.BasicUi:
wUI.reader = u.Reader
wUI.writer = u.Writer
wUI.errorWriter = u.ErrorWriter
wUI.baseUi = u
done = true
case *cli.ColoredUi:
ui = u.Ui
default:
return nil, fmt.Errorf("writer ui: unsupported Ui type: %T", ui)
}
}
if !done {
return nil, errors.New("failed to generate command UI")
}
return &wUI, nil
}
func (w *WriterUI) InputReader() io.Reader { return w.reader }
func (w *WriterUI) OutputWriter() io.Writer { return w.writer }
func (w *WriterUI) ErrorWriter() io.Writer { return w.errorWriter }
func (w *WriterUI) Output(message string) { w.Ui.Output(message) }
func (w *WriterUI) Info(message string) { w.Ui.Info(message) }
func (w *WriterUI) Warn(message string) { w.Ui.Warn(message) }
func (w *WriterUI) Error(message string) { w.Ui.Error(message) }View on GitHub (pinned to 482b49bf1a)
Solutions
- Pass a *cli.BasicUi or *cli.ColoredUi to NewWriterUI (wrap your custom Ui's Writer/Reader/ErrorWriter fields into a *cli.BasicUi instead)
- If you own a custom Ui type, extend the type switch in writer_ui.go to handle it, mapping its writer fields onto the WriterUI struct
- Check that you are not passing a typed-nil or incorrectly typed interface value; print %T of the argument to confirm its concrete type
Example fix
// before
wUI, err := NewWriterUI(&myCustomUi{w: os.Stdout})
// after
wUI, err := NewWriterUI(&cli.BasicUi{Writer: os.Stdout, ErrorWriter: os.Stderr, Reader: os.Stdin}) Defensive patterns
Strategy: type-guard
Validate before calling
func isSupportedUI(u cli.Ui) bool {
switch u.(type) {
case *cli.BasicUi, *cli.ColoredUi:
return true
}
return false
}
// call site:
if !isSupportedUI(myUi) { /* wrap into *cli.BasicUi first */ } Type guard
func asBasicUi(u cli.Ui) (*cli.BasicUi, bool) {
if bu, ok := u.(*cli.BasicUi); ok { return bu, true }
if cu, ok := u.(*cli.ColoredUi); ok {
return &cli.BasicUi{Reader: cu.Reader, Writer: cu.Writer, ErrorWriter: cu.ErrorWriter}, true
}
return nil, false
} Prevention
- Always construct the Ui as *cli.BasicUi or *cli.ColoredUi before passing to NewWriterUI
- Never wrap cli.Ui implementations in custom structs when handing them to this API
- Log %T of the Ui argument during integration debugging
- Check for typed-nil interfaces: a nil *myUi stored in a cli.Ui is non-nil interface but fails every case
When it happens
Trigger: Calling NewWriterUI with a Ui that is neither *cli.BasicUi nor *cli.ColoredUi — e.g. a custom cli.Ui implementation, a wrapped/proxy Ui type, or a typed nil interface. The test TestWriterUI_AskSecret covers the supported path; any third-party Ui hits the default branch.
Common situations: Embedding the library in a TUI or test harness that supplies its own cli.Ui implementation; passing a Ui wrapped in another struct; refactors that changed the concrete Ui type previously passed (e.g. ColoredUi replaced with a custom type).
Related errors
- CSI Plugin loaded incorrectly
- not a terminal
- both -n and -c set
- Allocation %q is running the following tasks: * %s Please
- Region not found
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/9f95c79f84b993eb.
Report an issue: GitHub.