Billionmail/BillionMail · error

disk quota exceeded

Error message

disk quota exceeded

What it means

incWritten is a write-progress callback for the zip compressor. It accumulates the number of bytes written to the archive and, when the compressor was created with a finite quota (z.quota > -1), fails the whole compression operation once the cumulative size exceeds that quota. This turns an unbounded archive job into a bounded one and protects the disk.

Source

Thrown at core/internal/service/compress/zip.go:54

	defer z.mutex.Unlock()
	z.quota = quota
}

// incWritten increases the size of already compressed file
func (z *Zipper) incWritten(n int64) (err error) {
	// if no limit is set, do nothing
	if z.quota < 0 {
		return nil
	}

	z.mutex.Lock()
	defer z.mutex.Unlock()

	z.written += n

	// check if exceeds the limit
	if z.quota > -1 && z.written > z.quota {
		err = errors.New("disk quota exceeded")
		return
	}

	return nil
}

// compressHelper compresses a file or directory
func (z *Zipper) compressHelper(zw *zip.Writer, path string, fi os.FileInfo, root string) error {
	header, err := zip.FileInfoHeader(fi)

	if err != nil {
		return err
	}

	header.Name = strings.TrimPrefix(strings.TrimPrefix(filepath.ToSlash(path), "./"), "/")
	header.Name = strings.TrimPrefix(strings.TrimPrefix(header.Name, root), "/")
	header.Method = zip.Deflate

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Increase or remove the quota (pass -1 for unlimited) when constructing the zip writer to match the real data size
  2. Exclude oversized files or split the compression job into multiple archives under the quota
  3. Free disk space / verify unit conversion (bytes vs MB) in the quota configuration
  4. Check the source directory size before compressing and fail fast with a clearer user-facing message

Example fix

// before
z, err := NewZip("out.zip", 1024*1024) // 1MB quota, data is 50MB
// after
z, err := NewZip("out.zip", -1) // unlimited, or quota sized from input estimate
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(srcDir); if err != nil || estimateSize(srcDir) > quota { return fmt.Errorf("source exceeds quota %d", quota) }

Try / catch

files, err := zipSvc.Compress(src, dst, quota)
if err != nil && strings.Contains(err.Error(), "disk quota exceeded") {
    // raise quota or split archive
}

Prevention

When it happens

Trigger: Calling Compress/CompressHelper on a source whose total uncompressed size exceeds the quota passed at compressor creation; any subsequent Write callback after written > quota aborts with this error.

Common situations: Backing up a directory that grew beyond the configured max archive size; accidentally passing a small quota (or a quota meant to be MB but interpreted as bytes); compressing large logs/uploads where no limit was intended but a stale quota config is in effect.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/7f98a752969ca834. Report an issue: GitHub.