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

  1. Ensure exactly one content source is set in the FileHandlerOption before calling ServeFileOption (FilePath, Data, File, or Reader).
  2. In the optionProvider, add a default/fallback branch that returns 404 instead of an empty option struct.
  3. Check that the path-matching logic in the provider doesn't produce empty options for unmatched paths.
  4. 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

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


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/45311172f5c7b55f. Report an issue: GitHub.