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
- Raise --lifetime to a value >= --ttl (e.g. `ipfs name publish --lifetime=168h --ttl=168h <path>`).
- Lower --ttl to at most the current lifetime (default 24h), or omit --ttl and let kubo cap it with min(DefaultRecordTTL, lifetime).
- 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
- Always pass --lifetime together with --ttl so their relationship is explicit.
- Clamp ttl to min(ttl, lifetime) in wrapper scripts before invoking the command.
- Remember the default lifetime is 24h; any --ttl over that must raise --lifetime too.
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
- cannot import key with name 'self'
- DHT timeout value must be >= 0
- invalid configuration profile: %s
- inline-limit %d exceeds maximum allowed size of %d bytes
- %s can't be used with UnixFS metadata like mode or modificat
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/2eb4b751ab783bcb.
Report an issue: GitHub.