wavetermdev/waveterm · error

stream file protocol error, no file info

Error message

stream file protocol error, no file info

What it means

ReadStreamToFileData wraps ReadFileStream and collects the file data/entries via callbacks. After a successful stream, fileData must have been set by the first-packet Info callback; if it is still nil the protocol produced no file info, so this error is returned.

Source

Thrown at pkg/remote/fileshare/fsutil/fsutil.go:144

	var entries []*wshrpc.FileInfo
	err := ReadFileStream(ctx, readCh, func(finfo wshrpc.FileInfo) {
		fileData = &wshrpc.FileData{
			Info: &finfo,
		}
	}, func(fileEntries []*wshrpc.FileInfo) error {
		entries = append(entries, fileEntries...)
		return nil
	}, func(data io.Reader) error {
		if _, err := io.Copy(&dataBuf, data); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	if fileData == nil {
		return nil, fmt.Errorf("stream file protocol error, no file info")
	}
	if !fileData.Info.IsDir {
		fileData.Data64 = base64.StdEncoding.EncodeToString(dataBuf.Bytes())
	} else {
		fileData.Entries = entries
	}
	return fileData, nil
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Retry the read after confirming the remote path exists and is accessible
  2. Upgrade wsh on both ends so the stream always begins with the Info packet
  3. Check remote permissions on the target path
  4. Inspect remote logs for responder-side stream aborts

Example fix

// before
data, err := fsutil.ReadStreamToFileData(ctx, ctl, path) // nil fileData
// after
if fi, statErr := remoteStat(ctx, ctl, path); statErr != nil || fi == nil {
    return nil, fmt.Errorf("remote path %q unavailable", path)
}
data, err := fsutil.ReadStreamToFileData(ctx, ctl, path)
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := remoteStat(ctx, ctl, path); err != nil || fi == nil {
    return fmt.Errorf("remote path %q is not readable", path)
}

Type guard

func streamHasInfo(data *fileshare.StreamData) bool { return data != nil && data.Info != nil }

Try / catch

data, err := fsutil.ReadStreamToFileData(ctx, ctl, path)
if err != nil && strings.Contains(err.Error(), "no file info") {
    return fmt.Errorf("remote returned an empty stream for %q — check permissions/version", path)
}

Prevention

When it happens

Trigger: Calling ReadStreamToFileData against a remote whose stream ends (readCh closed) without ever sending the first Info packet — empty/aborted stream from an incompatible or buggy responder.

Common situations: Remote aborted the stream immediately (permission change mid-read); wsh version mismatch causing the responder to close before sending info; zero-length stream due to remote filesystem error swallowed upstream.

Related errors


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