ipfs/kubo · error
mtime nanoseconds must be in range [1, 999999999]
Error message
mtime nanoseconds must be in range [1, 999999999]
What it means
Mtime sets a UnixFS timestamp (seconds plus nanoseconds, per the UnixFS spec's UnixTime metadata). The nanosecond sub-second field must be within [1, 999999999] (and is a uint32, so negatives are impossible); a larger value is meaningless in Go's time representation and is rejected.
Source
Thrown at core/coreiface/options/unixfs.go:413
return func(settings *UnixfsAddSettings) error {
settings.PreserveMtime = enable
return nil
}
}
// Mode represents a unix file mode
func (unixfsOpts) Mode(mode os.FileMode) UnixfsAddOption {
return func(settings *UnixfsAddSettings) error {
settings.Mode = mode
return nil
}
}
// Mtime represents a unix file mtime
func (unixfsOpts) Mtime(seconds int64, nsecs uint32) UnixfsAddOption {
return func(settings *UnixfsAddSettings) error {
if nsecs > 999999999 {
return errors.New("mtime nanoseconds must be in range [1, 999999999]")
}
settings.Mtime = time.Unix(seconds, int64(nsecs))
return nil
}
}
// IncludeEmptyDirs tells the adder to include empty directories in the DAG
func (unixfsOpts) IncludeEmptyDirs(include bool) UnixfsAddOption {
return func(settings *UnixfsAddSettings) error {
settings.IncludeEmptyDirs = include
settings.IncludeEmptyDirsSet = true
return nil
}
}
View on GitHub (pinned to 329838acdf)
Solutions
- Pass the sub-second remainder as nanoseconds: time.Unix(sec, 0) then t.Nanosecond() (always < 1e9), not the raw t.UnixNano()
- If your source is milliseconds, use nsecs = ms*1e6; for microseconds, use µs*1e3 — and verify the result stays under 1e9
- If you only have second precision, pass 0 for nsecs
Example fix
// before options.Unixfs.Mtime(t.Unix(), uint32(t.UnixNano())) // nsecs out of range // after options.Unixfs.Mtime(t.Unix(), uint32(t.Nanosecond()))
Defensive patterns
Strategy: validation
Validate before calling
func safeMtime(t time.Time) (int64, uint32, error) {
ns := t.Nanosecond() // always in [0, 999999999]
if ns < 0 {
return 0, 0, errors.New("negative nanoseconds")
}
return t.Unix(), uint32(ns), nil
}
sec, nsec, err := safeMtime(t)
if err != nil {
return err
}
opt := options.Unixfs.Mtime(sec, nsec) Type guard
func nsecsInRange(n uint32) bool {
return n <= 999999999
} Try / catch
opt := options.Unixfs.Mtime(sec, nsec)
if err := apply(opt); err != nil {
if strings.Contains(err.Error(), "mtime nanoseconds") {
// fall back to second precision
err = apply(options.Unixfs.Mtime(sec, 0))
}
if err != nil {
return err
}
} Prevention
- Always derive nanoseconds from time.Time.Nanosecond(), never from time.Time.UnixNano()
- Convert source units correctly: ms*1e6, µs*1e3, and verify < 1e9 before passing
- If you only need second precision, pass nsecs = 0
- Centralize timestamp conversion in one helper so the unit mistake happens in one auditable place
When it happens
Trigger: Calling options.Unixfs.Mtime(seconds, nsecs) with nsecs > 999999999 — e.g. Mtime(t.Unix(), t.Nanosecond()*1000) (mixing micro- and nanoseconds), or hardcoding 1000000000.
Common situations: Multiplying milliseconds or microseconds by the wrong factor (ms*1e6 vs µs*1e3) before passing; copying a full nanosecond-precision duration instead of its sub-second remainder; hand-rolled timestamp parsing producing out-of-range fractions.
Related errors
- unknown CID version: %d
- HAMT fanout must be a power of 2, between 8 and 1024 (got %d
- Import.UnixFSFileMaxLinks must be positive, got %d
- Import.UnixFSDirectoryMaxLinks must be non-negative, got %d
- Import.UnixFSHAMTDirectoryMaxFanout must be a power of 2, be
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/e332584805146cdf.
Report an issue: GitHub.