weaviate/weaviate · error
LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB must be >= 0
Error message
LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB must be >= 0
What it means
After parsing LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB as a float, FromEnv validates it is not negative and returns the literal error "LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB must be >= 0" otherwise, aborting startup. A negative size threshold is meaningless for the lazy-load size auto-detection logic.
Source
Thrown at usecases/config/environment.go:210
left = "no shard is warmed up"
}
logrus.Warnf("LAZY_LOAD_SHARD_WARMUP_MIN_OBJECTS is %d, so on a collection using lazy loading %s. "+
"A HOT tenant left out stays unloaded until first access. "+
"While it is unloaded the TTL sweep keeps its expired objects, async replication leaves a "+
"stale replica unrepaired, and MAXIMUM_ALLOWED_OBJECTS_COUNT stops counting it, so this "+
"node admits writes past its cap.",
minObjects, left)
}
// Lazy load shard size threshold for auto-detection (in GB)
// Determines at what total shard size auto-detection enables lazy loading
if v := os.Getenv("LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB"); v != "" {
asFloat, err := strconv.ParseFloat(v, 64)
if err != nil {
return fmt.Errorf("parse LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB as float: %w", err)
}
if asFloat < 0 {
return fmt.Errorf("LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB must be >= 0")
}
config.LazyLoadShardSizeThresholdGB = asFloat
} else {
config.LazyLoadShardSizeThresholdGB = DefaultLazyLoadShardSizeThresholdGB
}
if entcfg.Enabled(os.Getenv("FORCE_FULL_REPLICAS_SEARCH")) {
config.ForceFullReplicasSearch = true
}
if v := os.Getenv("TRANSFER_INACTIVITY_TIMEOUT"); v != "" {
timeout, err := time.ParseDuration(v)
if err != nil {
return fmt.Errorf("parse TRANSFER_INACTIVITY_TIMEOUT as duration: %w", err)
}
config.TransferInactivityTimeout = timeout
} else {
config.TransferInactivityTimeout = DefaultTransferInactivityTimeoutView on GitHub (pinned to 75aa4b6d11)
Solutions
- Set a non-negative value, e.g. LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB=0 (0 combined with threshold 0 semantics acts as always-lazy) or a realistic size like 20.
- Unset the variable to use the built-in default.
- Reject negative values in config linting/CI before deployment.
Example fix
// before LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB=-1 // after LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB=20
Defensive patterns
Strategy: validation
Validate before calling
v := os.Getenv("LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB")
if v != "" {
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return fmt.Errorf("not a float: %w", err)
}
if f < 0 {
return fmt.Errorf("LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB must be >= 0, got %v", f)
}
} Type guard
func validNonNegativeFloat(v string) bool {
f, err := strconv.ParseFloat(v, 64)
return err == nil && f >= 0
} Prevention
- Do not use negative values as feature-disabling sentinels; unset instead.
- Clamp computed thresholds to >= 0 in provisioning scripts.
- Add pre-deploy validation for all LAZY_LOAD_* numeric vars.
When it happens
Trigger: Set LAZY_LOAD_SHARD_SIZE_THRESHOLD_GB to a negative number such as "-1" (e.g. used as a "disable" sentinel from other tooling conventions); LoadConfig -> FromEnv returns this error at environment.go:210.
Common situations: Operators assuming -1 disables the feature (Go code does not treat it that way); misconfigured arithmetic in provisioning scripts producing negative values.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- invalid tag key:
- %s contains invalid entry %q; valid values are: %s
- invalid DEFAULT_VECTOR_INDEX %q, must be one of: %v
- ALLOWED_COMPRESSION_TYPES cannot be set when ALLOWED_VECTOR_
- %s lists multiple values (%s); %s must also be set to one of
AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04).
Data as JSON: /api/errors/67efb936159c925b.
Report an issue: GitHub.