wavetermdev/waveterm · error
no content available
Error message
no content available
What it means
ServeFileOption selects content from FileHandlerOption by priority: FilePath, Data, File, Reader. If none of these fields is set (or they are set to zero values), it falls through to the default case and returns this error. The library refuses to serve an HTTP response with no body source rather than writing an empty 200.
Source
Thrown at pkg/waveapp/waveapp.go:445
return fmt.Errorf("failed to write buffered data: %v", err)
}
}
if _, err := io.Copy(w, option.File); err != nil {
return fmt.Errorf("failed to copy from file: %v", err)
}
case option.Reader != nil:
if bufferedData != nil {
if _, err := w.Write(bufferedData); err != nil {
return fmt.Errorf("failed to write buffered data: %v", err)
}
}
if _, err := io.Copy(w, option.Reader); err != nil {
return fmt.Errorf("failed to copy from reader: %v", err)
}
default:
return fmt.Errorf("no content available")
}
return nil
}
func (c *Client) RegisterFilePrefixHandler(prefix string, optionProvider func(path string) (*FileHandlerOption, error)) {
c.UrlHandlerMux.PathPrefix(prefix).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
option, err := optionProvider(r.URL.Path)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if option == nil {
http.Error(w, "no content available", http.StatusNotFound)
return
}
if err := ServeFileOption(w, r, *option); err != nil {
http.Error(w, fmt.Sprintf("Failed to serve content: %v", err), http.StatusInternalServerError)View on GitHub (pinned to a4447c1563)
Solutions
- Ensure exactly one content source is set in the FileHandlerOption before calling ServeFileOption (FilePath, Data, File, or Reader).
- In the optionProvider, add a default/fallback branch that returns 404 instead of an empty option struct.
- Check that the path-matching logic in the provider doesn't produce empty options for unmatched paths.
- Log the requested path when this occurs to identify which URL triggers the empty option.
Example fix
// before
func provider(path string) (*waveapp.FileHandlerOption, error) {
if strings.HasSuffix(path, ".html") {
return &waveapp.FileHandlerOption{FilePath: filepath.Join(dir, path)}, nil
}
return &waveapp.FileHandlerOption{}, nil // empty -> "no content available"
}
// after
func provider(path string) (*waveapp.FileHandlerOption, error) {
fp := filepath.Join(dir, path)
if _, err := os.Stat(fp); err != nil {
return nil, os.ErrNotExist // caller can map to 404
}
return &waveapp.FileHandlerOption{FilePath: fp}, nil
} Defensive patterns
Strategy: validation
Validate before calling
func validateOption(o waveapp.FileHandlerOption) error {
if o.FilePath == "" && o.Data == nil && o.File == nil && o.Reader == nil {
return fmt.Errorf("FileHandlerOption has no content source")
}
return nil
}
// call before ServeFileOption
if err := validateOption(opt); err != nil {
http.NotFound(w, r)
return
} Type guard
func hasServeableContent(o waveapp.FileHandlerOption) bool {
return o.FilePath != "" || o.Data != nil || o.File != nil || o.Reader != nil
} Try / catch
err := waveapp.ServeFileOption(w, r, opt)
if err != nil && err.Error() == "no content available" {
http.NotFound(w, r) // or 500 if this indicates an internal bug
return
} Prevention
- Always set at least one content source in FileHandlerOption before serving.
- In optionProvider callbacks, return an explicit error (e.g. os.ErrNotExist) for unmatched paths instead of an empty struct.
- Unit-test the provider for edge paths (directories, missing files, favicon).
- Log the request path when the option is empty to find coverage gaps.
When it happens
Trigger: Calling ServeFileOption with a zero-value FileHandlerOption (waveapp.FileHandlerOption{}), or one where FilePath=="" and Data/File/Reader are all nil — e.g. a provider callback returned an empty option struct, or content was conditionally assigned and every branch was skipped.
Common situations: A RegisterFilePrefixHandler optionProvider builds the FileHandlerOption dynamically and forgets to set content for some paths (e.g. directory listing requests, favicon requests, or paths outside its data directory); a refactor renamed a field leaving the option empty.
Related errors
- Invalid UUID format
- failed to parse JSON: %v
- wcloud endpoint not set
- wcloud ping endpoint not set
- invalid AIMessage: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/45311172f5c7b55f.
Report an issue: GitHub.