{"record":{"id":"ea7cf9d8d4c52548","repo":"Billionmail/BillionMail","slug":"disk-quota-exceeded","errorCode":null,"errorMessage":"disk quota exceeded","messagePattern":"disk quota exceeded","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/compress/gzip.go","lineNumber":56,"sourceCode":"\tdefer z.mutex.Unlock()\n\tz.quota = quota\n}\n\n// incWritten increases the size of already compressed file\nfunc (z *GZipper) incWritten(n int64) (err error) {\n\t// if no limit is set, do nothing\n\tif z.quota < 0 {\n\t\treturn nil\n\t}\n\n\tz.mutex.Lock()\n\tdefer z.mutex.Unlock()\n\n\tz.written += n\n\n\t// check if exceeds the limit\n\tif z.quota > -1 && z.written > z.quota {\n\t\terr = errors.New(\"disk quota exceeded\")\n\t\treturn\n\t}\n\n\treturn nil\n}\n\n// compressHelper packs a file or directory into tar\nfunc (z *GZipper) compressHelper(tw *tar.Writer, path string, fi os.FileInfo, root string) error {\n\theader, err := tar.FileInfoHeader(fi, \"\")\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// compatible with Linux path rules\n\theader.Name = strings.TrimPrefix(strings.TrimPrefix(filepath.ToSlash(path), \"./\"), \"/\")\n\theader.Name = strings.TrimPrefix(strings.TrimPrefix(header.Name, root), \"/\")\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/compress/gzip.go#L38-L74","documentation":"GzipUnpacker.incWritten tracks every byte written through a quota-limited writer while compressing. When the cumulative bytes written exceed the configured quota (z.quota, where -1 means unlimited), it returns this error to abort the compression. It is a safety guard against runaway disk usage, not an OS-level quota failure.","triggerScenarios":"Calling GzipUnpacker.Compress (or Decompress) on data whose total output exceeds the quota set via SetQuota/constructor when quota > -1; e.g. compressing a multi-GB directory into an archive whose output surpasses the limit.","commonSituations":"Admins configured a small disk quota for temp/backup space; users compressing large log or media directories; quota left at a stale low default after data growth.","solutions":["Increase the quota via SetQuota before compressing, based on the expected output size","Remove the quota by setting it to -1 if disk space is managed elsewhere","Free disk space or move the output to a larger volume and retry","Pre-check the source size (du/os.Stat walk) and ensure quota comfortably exceeds expected compressed size"],"exampleFix":"// before\nu, _ := compress.NewGzipUnpacker(1024*1024) // 1MB quota\nerr := u.Compress(\"out.tar.gz\", bigDir)\n// after\nu, _ := compress.NewGzipUnpacker(-1) // unlimited, or size-based quota\nerr := u.Compress(\"out.tar.gz\", bigDir)","handlingStrategy":"validation","validationCode":"var total int64\nfilepath.WalkDir(src, func(_ string, d fs.DirEntry, err error) error {\n\tif err != nil { return err }\n\tif !d.IsDir() { if i, _ := d.Info(); i != nil { total += i.Size() } }\n\treturn nil\n})\nif quota > -1 && total > quota { /* raise quota or reject job */ }","typeGuard":null,"tryCatchPattern":"if err := u.Compress(dst, src...); err != nil && strings.Contains(err.Error(), \"disk quota exceeded\") {\n\t// raise quota and retry or alert operator\n}","preventionTips":["Size the quota from source statistics before every compression job","Set quota = -1 when disk usage is managed by the OS or cgroups","Monitor written bytes via incWritten and fail early with your own metric","Alert on jobs that repeatedly hit the quota instead of silently retrying"],"tags":["go","compression","gzip","disk-quota"],"backgroundTag":"disk-quota-exceeded","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}