ipfs/kubo · error

ttl (%s) must not be greater than lifetime (%s)

Error message

ttl (%s) must not be greater than lifetime (%s)

What it means

`ipfs name publish` validates that an explicitly passed `--ttl` duration does not exceed the record's `--lifetime` (which defaults to ipns.DefaultRecordLifetime). IPNS records are not cached past their validity, so a TTL longer than the lifetime is contradictory and rejected at publish time before any record is signed or broadcast.

Source

Thrown at core/commands/name/publish.go:162

			options.Name.AllowDelegated(allowDelegated),
			options.Name.Key(kname),
			options.Name.ValidTime(validTime),
			options.Name.CompatibleWithV1(compatibleWithV1),
		}

		// A record is not cached past its validity, so the TTL must not exceed the
		// lifetime. An explicit --ttl over the lifetime is an error; the default
		// --ttl is capped to the lifetime instead.
		if ttl, found := req.Options[ttlOptionName].(string); found {
			d, err := time.ParseDuration(ttl)
			if err != nil {
				return err
			}
			if d < 0 {
				return fmt.Errorf("ttl must not be negative, got %s", ttl)
			}
			if d > validTime {
				return fmt.Errorf("ttl (%s) must not be greater than lifetime (%s)", d, validTime)
			}

			opts = append(opts, options.Name.TTL(d))
		} else {
			opts = append(opts, options.Name.TTL(min(ipns.DefaultRecordTTL, validTime)))
		}

		if sequence, found := req.Options[sequenceOptionName].(uint64); found {
			opts = append(opts, options.Name.Sequence(sequence))
		}

		p, err := cmdutils.PathOrCidPath(req.Arguments[0])
		if err != nil {
			return err
		}

		if verifyExists, _ := req.Options[resolveOptionName].(bool); verifyExists {
			_, err := api.ResolveNode(req.Context, p)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Raise --lifetime to a value >= --ttl (e.g. `ipfs name publish --lifetime=168h --ttl=168h <path>`).
  2. Lower --ttl to at most the current lifetime (default 24h), or omit --ttl and let kubo cap it with min(DefaultRecordTTL, lifetime).
  3. Fix any script that computes ttl/lifetime so it asserts ttl <= lifetime before invoking the command.

Example fix

// before
ipfs name publish --ttl=72h /ipfs/<cid>            // fails: default lifetime is 24h
// after
ipfs name publish --lifetime=72h --ttl=72h /ipfs/<cid>
Defensive patterns

Strategy: validation

Validate before calling

lifetime, _ := time.ParseDuration("24h")
ttl, _ := time.ParseDuration("72h")
if ttl > lifetime {
    return fmt.Errorf("ttl (%s) must not exceed lifetime (%s)", ttl, lifetime)
}

Prevention

When it happens

Trigger: Running `ipfs name publish --ttl <d> ...` where the parsed ttl duration d > validTime, i.e. the user passed --ttl greater than the --lifetime value (or greater than the default lifetime when --lifetime is unset).

Common situations: Users copying a --ttl from an example with a large value like 168h while --lifetime defaults to 24h; scripts setting --ttl but forgetting to raise --lifetime to match; confusion between TTL semantics (cache freshness) and lifetime (record validity).

Related errors


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