seaweedfs/seaweedfs · error

dirIdleEvictSec: %s

Error message

dirIdleEvictSec: %s

What it means

runFuse in weed/command/fuse_std.go parses FUSE helper-style options (space/dash/comma separated name=value pairs, e.g. `weed fuse /mnt/sw -o filer=localhost:8888,readOnly=true`) before daemonizing into a master/child pair and calling runMount. dirIdleEvictSec (seconds an idle directory entry stays cached before eviction) is parsed with strconv.ParseInt(value, 0, 32): base 0 also accepts 0x/0o/0b prefixes; the value must be a whole number within int32 range. The panic fires on duration strings like '30m', floats, or a bare flag (a bare flag without '=' is assigned the literal value "true" by the tokenizer (fuse_std.go:46,57,102), which then fails numeric parsing).

Source

Thrown at weed/command/fuse_std.go:165

			if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
				intValue := int(parsed)
				mountOptions.chunkSizeLimitMB = &intValue
			} else {
				panic(fmt.Errorf("chunkSizeLimitMB: %s", err))
			}
		case "cacheMetaTtlSec":
			if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
				intValue := int(parsed)
				mountOptions.cacheMetaTtlSec = &intValue
			} else {
				panic(fmt.Errorf("cacheMetaTtlSec: %s", err))
			}
		case "dirIdleEvictSec":
			if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
				intValue := int(parsed)
				mountOptions.dirIdleEvictSec = &intValue
			} else {
				panic(fmt.Errorf("dirIdleEvictSec: %s", err))
			}
		case "concurrentWriters":
			if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
				intValue := int(parsed)
				mountOptions.concurrentWriters = &intValue
			} else {
				panic(fmt.Errorf("concurrentWriters: %s", err))
			}
		case "concurrentReaders":
			if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
				intValue := int(parsed)
				mountOptions.concurrentReaders = &intValue
			} else {
				panic(fmt.Errorf("concurrentReaders: %s", err))
			}
		case "cacheDir":
			mountOptions.cacheDirForRead = &parameter.value
		case "cacheCapacityMB":

View on GitHub (pinned to 1c926e8fac)

Solutions

  1. Pass whole seconds: dirIdleEvictSec=1800 for 30 minutes
  2. Strip unit suffixes and decimal points
  3. Keep the value within int32 range
  4. Use name=value form, not a bare flag

Example fix

// before
weed fuse /mnt/sw -o "filer=localhost:8888,dirIdleEvictSec=30m"

// after
weed fuse /mnt/sw -o "filer=localhost:8888,dirIdleEvictSec=1800"
Defensive patterns

Strategy: validation

Validate before calling

if v, ok := opts["dirIdleEvictSec"]; ok {
	if _, err := strconv.ParseInt(v, 0, 32); err != nil {
		return fmt.Errorf("dirIdleEvictSec must be int32 seconds (no units): %w", err)
	}
}

Type guard

func isInt32Option(v string) bool {
	_, err := strconv.ParseInt(v, 0, 32)
	return err == nil
}

Prevention

When it happens

Trigger: -o dirIdleEvictSec=30m; dirIdleEvictSec=1.5; bare -o dirIdleEvictSec.

Common situations: Tuning copied from blog posts that show human-readable durations; options migrated from yaml config keys that accept durations.

Related errors


AI-assisted analysis of seaweedfs/seaweedfs@1c926e8fac (2026-08-15). Data as JSON: /api/errors/008e9867a5fdc0dc. Report an issue: GitHub.