gohugoio/hugo · error

failed to parse timeout

Error message

failed to parse timeout: %s

What it means

Returned by Config.CompileConfig when the `timeout` config string cannot be parsed as a Go duration. The code first tries strconv.Atoi: if it succeeds, the number is treated as seconds and 's' is appended; otherwise it calls time.ParseDuration directly. Failure of that final parse yields this error wrapping the parse error.

Solutions

  1. Use a plain integer (interpreted as seconds) e.g. `timeout = 60`.
  2. Or use Go duration syntax e.g. `timeout = "45s"`, `timeout = "5m"`.
  3. Remove invalid unit words like 'sec', 'min', 'day'.

Example fix

// before
timeout = "30sec"
// after
timeout = "30s"
Defensive patterns

Strategy: validation

Validate before calling

func validateTimeout(s string) error {
  if _, err := strconv.Atoi(s); err == nil { return nil }
  if _, err := time.ParseDuration(s); err == nil { return nil }
  return fmt.Errorf("invalid timeout %q: use integer seconds or Go duration", s)
}

Prevention

When it happens

Trigger: Setting `timeout` in hugo.toml/yaml/json to a value that is neither a bare integer (seconds) nor a valid Go duration string (e.g. '30', '2m', '1h30m').

Common situations: Porting configs from other tools that accept human durations like '1 day' or '1d', or typos like '30sec', '5 mins', 'fast'.

Understand the failure class

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/6577fc45d50834aa. Report an issue: GitHub.

Appendix: source

Thrown at config/allconfig/allconfig.go:279

	x.StaticDir6 = nil
	x.StaticDir7 = nil
	x.StaticDir8 = nil
	x.StaticDir9 = nil
	x.StaticDir10 = nil

	return &x
}

func (c *Config) CompileConfig(logger loggers.Logger) error {
	var transientErr error
	s := c.Timeout
	if _, err := strconv.Atoi(s); err == nil {
		// A number, assume seconds.
		s = s + "s"
	}
	timeout, err := time.ParseDuration(s)
	if err != nil {
		return fmt.Errorf("failed to parse timeout: %s", err)
	}
	disabledKinds := make(map[string]bool)
	for _, kind := range c.DisableKinds {
		kind = strings.ToLower(kind)
		if newKind := kinds.IsDeprecatedAndReplacedWith(kind); newKind != "" {
			logger.Deprecatef(false, "Kind %q used in disableKinds is deprecated, use %q instead.", kind, newKind)
			// Legacy config.
			kind = newKind
		}
		if kinds.GetKindAny(kind) == "" {
			logger.Warnf("Unknown kind %q in disableKinds configuration.", kind)
			continue
		}
		disabledKinds[kind] = true
	}
	kindOutputFormats := make(map[string]output.Formats)
	isRssDisabled := disabledKinds["rss"]
	outputFormats := c.OutputFormats.Config

View on GitHub (pinned to 52c9bd7908)