{"record":{"id":"66688472f0df9c80","repo":"dagger/dagger","slug":"metadata-prune-target-estimated-bytes-must-be-pos","errorCode":null,"errorMessage":"metadata prune: target estimated bytes must be positive and lower than maximum","messagePattern":"metadata prune: target estimated bytes must be positive and lower than maximum","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dagql/cache_prune.go","lineNumber":127,"sourceCode":"\tstarted := time.Now()\n\treport.MaximumEstimatedBytes = maximumBytes\n\treport.TargetEstimatedBytes = targetBytes\n\tdefer func() {\n\t\treport.Duration = time.Since(started)\n\t\tif report.Triggered && c != nil {\n\t\t\tc.traceMetadataPruneFinished(ctx, report, rerr)\n\t\t\tmetadataPruneLog(ctx, report, rerr)\n\t\t}\n\t}()\n\n\tif c == nil {\n\t\treturn report, fmt.Errorf(\"metadata prune: nil cache\")\n\t}\n\tif maximumBytes <= 0 {\n\t\treturn report, fmt.Errorf(\"metadata prune: maximum estimated bytes must be positive\")\n\t}\n\tif targetBytes <= 0 || targetBytes >= maximumBytes {\n\t\treturn report, fmt.Errorf(\"metadata prune: target estimated bytes must be positive and lower than maximum\")\n\t}\n\tif err := ctx.Err(); err != nil {\n\t\treturn report, err\n\t}\n\n\tc.egraphMu.Lock()\n\treport.BeforeCompaction = c.cacheMetadataEstimateLocked()\n\treport.AfterInitialCompaction = report.BeforeCompaction\n\treport.AfterPrune = report.BeforeCompaction\n\tif report.BeforeCompaction.EstimatedBytes <= maximumBytes {\n\t\tc.egraphMu.Unlock()\n\t\treturn report, nil\n\t}\n\treport.Triggered = true\n\tc.traceMetadataPruneStarted(ctx, maximumBytes, targetBytes)\n\t_, report.InitialCompactionOldClassSlots, report.InitialCompactionNewClassSlots = c.compactEqClassesLocked(true)\n\treport.AfterInitialCompaction = c.cacheMetadataEstimateLocked()\n\treport.AfterPrune = report.AfterInitialCompaction","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/dagql/cache_prune.go#L109-L145","documentation":"PruneMetadataEstimate requires 0 < targetBytes < maximumBytes: the target must be positive and strictly below the maximum so prune can shrink the cache to a level under the cap. Violating this invariant aborts the prune with this error.","triggerScenarios":"Calling PruneMetadataEstimate with targetBytes <= 0, or targetBytes >= maximumBytes (equal values included) — e.g. miscomputed ratios (target==max), inverted arguments, or zero target from unset config.","commonSituations":"Configuration where target and max are set to the same value; passing arguments in the wrong order (target, max) swapped; target derived as a percentage that rounds to 0 or 100%.","solutions":["Ensure targetBytes is strictly between 0 and maximumBytes","Check argument order and derivation (e.g. target = max * 0.8)","Add caller-side validation before invoking prune"],"exampleFix":"// before\nreport, err := cache.PruneMetadataEstimate(ctx, max, max) // invalid\n// after\ntarget := max * 80 / 100\nreport, err := cache.PruneMetadataEstimate(ctx, max, target)","handlingStrategy":"validation","validationCode":"if targetBytes <= 0 || targetBytes >= maxBytes {\n    return fmt.Errorf(\"targetBytes must be in (0, %d), got %d\", maxBytes, targetBytes)\n}\nreport, err := cache.PruneMetadataEstimate(ctx, maxBytes, targetBytes)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive target as a fraction of max (e.g. 80%) rather than independent config","Check argument order at every call site","Add a config sanity check: 0 < target < max"],"tags":["go","cache","gc","validation","config"],"backgroundTag":"invalid-prune-limit","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}