{"record":{"id":"07bb1f445926a1d2","repo":"Billionmail/BillionMail","slug":"parse-maildirsize-line-d-invalid-size-s-w","errorCode":null,"errorMessage":"parse maildirsize line %d: invalid size '%s': %w","messagePattern":"parse maildirsize line (.+?): invalid size '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_boxes/update_used_space.go","lineNumber":226,"sourceCode":"\t\t}\n\n\t\tparts := strings.Fields(line)\n\t\tif len(parts) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tif lineNo == 1 {\n\n\t\t\tcontinue\n\t\t}\n\n\t\tsizeStr := parts[0]\n\n\t\tsizeStr = strings.TrimSuffix(sizeStr, \"S\")\n\n\t\tv, err := strconv.ParseInt(sizeStr, 10, 64)\n\t\tif err != nil {\n\t\t\treturn 0, fmt.Errorf(\"parse maildirsize line %d: invalid size '%s': %w\", lineNo, sizeStr, err)\n\t\t}\n\t\ttotal += v\n\t}\n\n\tif err := scanner.Err(); err != nil {\n\t\treturn 0, fmt.Errorf(\"scan maildirsize failed: %w\", err)\n\t}\n\n\treturn total, nil\n}\n\n// domain.current_usage\nfunc aggregateDomainUsage(ctx context.Context) {\n\n\tif atomic.LoadInt32(&domainUsageColumnEnsured) == 0 {\n\t\tif _, err := g.DB().Exec(ctx, \"ALTER TABLE domain ADD COLUMN IF NOT EXISTS current_usage BIGINT NOT NULL DEFAULT 0\"); err != nil {\n\t\t\tg.Log().Warning(ctx, \"ensure domain.current_usage column failed\", err)\n\t\t}","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_boxes/update_used_space.go#L208-L244","documentation":"readMaildirsize parses Dovecot's maildirsize file to compute a mailbox's used space. Each data line starts with a byte count that may be suffixed with 'S' (messages) which is stripped before parsing. This error is thrown when strconv.ParseInt cannot convert the size token to an int64, meaning the maildirsize file is corrupted or in an unexpected format.","triggerScenarios":"A maildirsize line whose first whitespace-separated field is not a decimal integer (after trimming a trailing 'S'), e.g. alphabetic garbage, truncated writes, or a header line miscounted as a data line.","commonSituations":"Disk-full or crash during maildirsize write leaving a partial line; manual edits of the maildirsize file; a mail delivery tool writing a nonstandard size field; NFS corruption of the maildir metadata.","solutions":["Inspect the maildirsize file at the reported line number and fix or remove the malformed size token","Delete the maildirsize file and let Dovecot recalculate it (rebuild quota index)","Ensure quota rules are consistent so tools writing maildirsize use the standard '<bytes> <count>' format","Wrap ParseInt with a guard that skips empty/unparseable tokens instead of failing the whole read"],"exampleFix":"// before\nv, err := strconv.ParseInt(sizeStr, 10, 64)\nif err != nil {\n    return 0, fmt.Errorf(\"parse maildirsize line %d: invalid size '%s': %w\", lineNo, sizeStr, err)\n}\n// after\nif sizeStr == \"\" {\n    continue // skip blank size token\n}\nv, err := strconv.ParseInt(sizeStr, 10, 64)\nif err != nil {\n    return 0, fmt.Errorf(\"parse maildirsize line %d: invalid size '%s': %w\", lineNo, sizeStr, err)\n}","handlingStrategy":"validation","validationCode":"data, err := os.ReadFile(maildirsizePath)\nif err != nil { return err }\nfor i, line := range strings.Split(string(data), \"\\n\") {\n    if i == 0 { continue } // header\n    sizeStr := strings.TrimSuffix(strings.Fields(line)[0], \"S\")\n    if _, err := strconv.ParseInt(sizeStr, 10, 64); err != nil {\n        return fmt.Errorf(\"malformed maildirsize line %d\", i+1)\n    }\n}","typeGuard":"func isValidMaildirSize(tok string) bool {\n    _, err := strconv.ParseInt(strings.TrimSuffix(tok, \"S\"), 10, 64)\n    return err == nil\n}","tryCatchPattern":"total, err := readMaildirsize(path)\nif errors.Is(err, strconv.ErrSyntax) || strings.Contains(err.Error(), \"invalid size\") {\n    log.Warn(\"corrupt maildirsize, rebuilding\")\n    os.Remove(path) // let Dovecot recalc\n    return recalcUsageFromMaildir(path)\n}\nif err != nil { return err }","preventionTips":["Never hand-edit maildirsize; delete it and let Dovecot rebuild","Monitor for disk-full events that truncate quota files","Validate the file after any maildir migration or NFS failover"],"tags":["maildir","quota","file-parsing","go"],"backgroundTag":"maildirsize-corrupt-line","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"}