wavetermdev/waveterm · error

circular file must have a max size

Error message

circular file must have a max size

What it means

A circular file is a fixed-size ring buffer of parts, so it requires a positive MaxSize to size the ring. MakeFile rejects Circular=true combined with MaxSize <= 0 because there would be no space to write any data.

Source

Thrown at pkg/filestore/blockstore.go:120

func (WaveFile) UseDBMap() {}

type FileData struct {
	ZoneId  string `json:"zoneid"`
	Name    string `json:"name"`
	PartIdx int    `json:"partidx"`
	Data    []byte `json:"data"`
}

func (FileData) UseDBMap() {}

// synchronous (does not interact with the cache)
func (s *FileStore) MakeFile(ctx context.Context, zoneId string, name string, meta wshrpc.FileMeta, opts wshrpc.FileOpts) error {
	if opts.MaxSize < 0 {
		return fmt.Errorf("max size must be non-negative")
	}
	if opts.Circular && opts.MaxSize <= 0 {
		return fmt.Errorf("circular file must have a max size")
	}
	if opts.Circular && opts.IJson {
		return fmt.Errorf("circular file cannot be ijson")
	}
	if opts.Circular {
		if opts.MaxSize%partDataSize != 0 {
			opts.MaxSize = (opts.MaxSize/partDataSize + 1) * partDataSize
		}
	}
	if opts.IJsonBudget > 0 && !opts.IJson {
		return fmt.Errorf("ijson budget requires ijson")
	}
	if opts.IJsonBudget < 0 {
		return fmt.Errorf("ijson budget must be non-negative")
	}
	return withLock(s, zoneId, name, func(entry *CacheEntry) error {
		if entry.File != nil {
			return fs.ErrExist

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set a positive MaxSize when Circular is true, ideally a multiple of partDataSize (it will be rounded up automatically).
  2. Guard the call site: only set Circular=true after validating MaxSize > 0.
  3. If the file should be unbounded, do not use Circular — omit it.

Example fix

// before
opts := wshrpc.FileOpts{Circular: true} // MaxSize left at 0
// after
opts := wshrpc.FileOpts{Circular: true, MaxSize: 4 * 1024 * 1024}
Defensive patterns

Strategy: validation

Validate before calling

func validCircularOpts(opts wshrpc.FileOpts) bool {
	return !opts.Circular || opts.MaxSize > 0
}
if !validCircularOpts(opts) {
	return fmt.Errorf("circular requires MaxSize > 0")
}

Try / catch

if err := store.MakeFile(ctx, zoneId, name, meta, opts); err != nil {
	if strings.Contains(err.Error(), "circular file must have a max size") {
		opts.MaxSize = defaultCircularMaxSize // e.g. 4MB
		err = store.MakeFile(ctx, zoneId, name, meta, opts)
	}
	if err != nil {
		return err
	}
}

Prevention

When it happens

Trigger: Calling MakeFile with opts.Circular = true and opts.MaxSize == 0 or < 0 — typically forgetting to set MaxSize at all (zero value) when requesting a circular file.

Common situations: Constructing FileOpts for a log-style circular file and leaving MaxSize unset (Go zero value 0); copying opts from a non-circular use case where MaxSize was intentionally 0; config key for max size missing so it defaults to 0.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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