{"record":{"id":"0b8bd8b2cd0cb9da","repo":"ipfs/kubo","slug":"provide-dht-interval-0-no-longer-disables-the-prov","errorCode":null,"errorMessage":"Provide.DHT.Interval=0 no longer disables the provide system on its own; set Provide.Enabled explicitly: Provide.Enabled=false to fully disable providing, or Provide.Enabled=true to keep ad-hoc 'ipfs provide once' and fast-provide-root working while skipping the periodic reprovide schedule","messagePattern":"Provide\\.DHT\\.Interval=0 no longer disables the provide system on its own; set Provide\\.Enabled explicitly: Provide\\.Enabled=false to fully disable providing, or Provide\\.Enabled=true to keep ad-hoc 'ipfs provide once' and fast-provide-root working while skipping the periodic reprovide schedule","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/provide.go","lineNumber":229,"sourceCode":"\t// Validate Provide.DHT.Interval\n\tif !cfg.DHT.Interval.IsDefault() {\n\t\tinterval := cfg.DHT.Interval.WithDefault(DefaultProvideDHTInterval)\n\t\tif interval > amino.DefaultProvideValidity {\n\t\t\treturn fmt.Errorf(\"Provide.DHT.Interval (%v) must be less than or equal to DHT provider record validity (%v)\", interval, amino.DefaultProvideValidity)\n\t\t}\n\t\tif interval < 0 {\n\t\t\treturn fmt.Errorf(\"Provide.DHT.Interval must be non-negative, got %v\", interval)\n\t\t}\n\t\t// Provide.DHT.Interval=0 used to disable the entire provide system as a\n\t\t// side effect. It now disables only the periodic reprovide schedule:\n\t\t// new CIDs still announce via fast-provide-root and 'ipfs provide once'.\n\t\t// Operators upgrading from earlier kubo versions must opt in to one of\n\t\t// the two semantics by setting Provide.Enabled explicitly:\n\t\t//   - Provide.Enabled=false fully disables providing (the old behaviour).\n\t\t//   - Provide.Enabled=true keeps ad-hoc providing while disabling the\n\t\t//     periodic reprovide schedule.\n\t\tif interval == 0 && cfg.Enabled == Default {\n\t\t\treturn fmt.Errorf(\"Provide.DHT.Interval=0 no longer disables the provide system on its own; set Provide.Enabled explicitly: \" +\n\t\t\t\t\"Provide.Enabled=false to fully disable providing, or Provide.Enabled=true to keep ad-hoc 'ipfs provide once' \" +\n\t\t\t\t\"and fast-provide-root working while skipping the periodic reprovide schedule\")\n\t\t}\n\t}\n\n\t// Validate MaxWorkers\n\tif !cfg.DHT.MaxWorkers.IsDefault() {\n\t\tmaxWorkers := cfg.DHT.MaxWorkers.WithDefault(DefaultProvideDHTMaxWorkers)\n\t\tif maxWorkers <= 0 {\n\t\t\treturn fmt.Errorf(\"Provide.DHT.MaxWorkers must be positive, got %d\", maxWorkers)\n\t\t}\n\t}\n\n\t// Validate DedicatedPeriodicWorkers\n\tif !cfg.DHT.DedicatedPeriodicWorkers.IsDefault() {\n\t\tworkers := cfg.DHT.DedicatedPeriodicWorkers.WithDefault(DefaultProvideDHTDedicatedPeriodicWorkers)\n\t\tif workers < 0 {\n\t\t\treturn fmt.Errorf(\"Provide.DHT.DedicatedPeriodicWorkers must be non-negative, got %d\", workers)","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/config/provide.go#L211-L247","documentation":"Historically Provide.DHT.Interval=0 silently disabled the entire provide system as a side effect. Kubo now splits the semantics: Provide.Enabled=false fully disables providing, while Provide.Enabled=true keeps ad-hoc 'ipfs provide once' and fast-provide-root but skips the periodic reprovide schedule. Because Interval=0 alone is ambiguous, node startup refuses it when Provide.Enabled is left at its unset default, forcing the operator to opt in explicitly.","triggerScenarios":"Node startup with Provide.DHT.Interval set to exactly 0 while cfg.Provide.Enabled is unset (config.Flag Default), i.e. an operator relying on the old Interval=0 behavior without stating which semantics they want.","commonSituations":"Upgrading a node whose older config used Interval=0 to disable providing; migration scripts copying the old trick; users following outdated guides.","solutions":["Add `ipfs config --json Provide.Enabled false` to fully disable providing (old behavior), or `ipfs config --json Provide.Enabled true` to keep ad-hoc providing without the periodic schedule","Alternatively set Provide.DHT.Interval to a positive value if periodic reproviding was not actually meant to be disabled","Restart the daemon after setting Provide.Enabled explicitly"],"exampleFix":"// before\n\"Provide\": { \"DHT\": { \"Interval\": \"0s\" } }\n// after\n\"Provide\": { \"Enabled\": false, \"DHT\": { \"Interval\": \"0s\" } }","handlingStrategy":"validation","validationCode":"if iv := cfg.Provide.DHT.Interval; !iv.IsDefault() && iv.WithDefault(config.DefaultProvideDHTInterval) == 0 && cfg.Provide.Enabled == config.Default {\n\treturn errors.New(\"set Provide.Enabled explicitly when DHT.Interval=0\")\n}","typeGuard":null,"tryCatchPattern":"if err := config.ValidateProvideConfig(cfg.Provide); err != nil {\n\tif strings.Contains(err.Error(), \"no longer disables the provide system\") {\n\t\tcfg.Provide.Enabled = config.False // or True, per intended semantics\n\t}\n\treturn err\n}","preventionTips":["Always set Provide.Enabled explicitly when using Interval=0","Update legacy configs that relied on Interval=0 disabling everything","Enabled=false fully disables; Enabled=true keeps ad-hoc provide but skips the periodic schedule"],"tags":["config","validation","migration","breaking-change"],"backgroundTag":"ambiguous-config-default","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}