ipfs/kubo · error

unexpected keystore suffix %q, expected "0" or "1"

Error message

unexpected keystore suffix %q, expected "0" or "1"

What it means

This error comes from validateKeystoreSuffix in core/node/provider.go, which guards the alternating-keystore namespace scheme used by the reprovide/provider system. The upstream keystore layout alternates between two suffix directories, "0" and "1"; any other suffix means the code would be operating on a directory it does not understand. The check exists specifically so a future upstream scheme change cannot cause os.RemoveAll to delete unrelated directories. If you see it, the computed keystore suffix fell outside the two known values.

Source

Thrown at core/node/provider.go:89

	keystoreDatastoreKey = datastore.NewKey("keystore")
)

// providerLog is the go-log subsystem used for provide/reprovide-related
// messages emitted from kubo's own orchestration code. It shares the
// "provider" subsystem name with boxo's provider package so users can set
// GOLOG_LOG_LEVEL=provider=<level> to control both layers at once. See
// docs/debug-guide.md for the full list of provide-related subsystems.
var providerLog = log.Logger("provider")

var errAcceleratedDHTNotReady = errors.New("AcceleratedDHTClient: routing table not ready")

// validateKeystoreSuffix rejects any suffix other than "0" or "1".
// The upstream library uses these two values as alternating namespace
// identifiers. Validating here prevents accidental deletion of unrelated
// directories via os.RemoveAll if the upstream ever changes its scheme.
func validateKeystoreSuffix(suffix string) error {
	if suffix != "0" && suffix != "1" {
		return fmt.Errorf("unexpected keystore suffix %q, expected \"0\" or \"1\"", suffix)
	}
	return nil
}

// Interval between reprovide queue monitoring checks for slow reprovide alerts.
// Used when Provide.DHT.SweepEnabled=true
const reprovideAlertPollInterval = 15 * time.Minute

// Number of consecutive polling intervals with sustained queue growth before
// triggering a slow reprovide alert (3 intervals = 45 minutes).
// Used when Provide.DHT.SweepEnabled=true
const consecutiveAlertsThreshold = 3

// DHTProvider is an interface for providing keys to a DHT swarm. It holds a
// state of keys to be advertised, and is responsible for periodically
// publishing provider records for these keys to the DHT swarm before the
// records expire.
type DHTProvider interface {

View on GitHub (pinned to 329838acdf)

Solutions

  1. Check the version of the upstream provider library in go.mod against what kubo expects; align it (go get <lib>@<pin> + make mod_tidy).
  2. Inspect the keystore directories under the repo datastore path; remove or rename any directory whose suffix is not "0" or "1" (after backing up).
  3. Search the code path computing the suffix for a regression and fix the calculation so only "0"/"1" are produced.
  4. If neither suffix applies, this is a hard stop by design — do not bypass the guard; report the upstream scheme change to kubo/boxo.

Example fix

// before
suffix := fmt.Sprint(counter) // may yield "2", "3", ...
if err := validateKeystoreSuffix(suffix); err != nil { ... }
// after
suffix := "0"
if counter%2 == 1 {
    suffix = "1"
}
if err := validateKeystoreSuffix(suffix); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

func safeKeystoreSuffix(n int) (string, error) {
    s := strconv.Itoa(n % 2)
    if s != "0" && s != "1" {
        return "", fmt.Errorf("computed suffix %q outside {0,1}", s)
    }
    return s, nil
}

Type guard

func isValidKeystoreSuffix(s string) bool { return s == "0" || s == "1" }

Prevention

When it happens

Trigger: Calling into the keystore swap/cleanup path when the suffix variable passed to validateKeystoreSuffix is anything other than the literal "0" or "1" — typically a bug in the caller computing the suffix, or an upstream library version that changed its naming scheme.

Common situations: Running a kubo build paired with a newer/older version of the upstream provider library that altered its keystore directory naming; local manual edits or scripts that created extra keystore directories; a regression in the alternating-suffix calculation.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/a98fbab1d4fc4d48. Report an issue: GitHub.