cilium/cilium · error
clockSource is nil
Error message
clockSource is nil
What it means
NewCTTimeToSecConverter builds a timestamp-to-seconds converter based on the agent-reported clocksource. A nil clockSource argument gives no mode information, so the constructor returns this error immediately instead of dereferencing nil. It is a fail-fast guard for callers that skipped clocksource discovery.
Source
Thrown at pkg/maps/timestamp/timestamp.go:104
return t / 1000000000, nil
case models.ClockSourceModeJiffies:
j, err := probes.Jiffies()
if err != nil {
return 0, err
}
return j >> bpfMonoScaler, nil
default:
return 0, fmt.Errorf("invalid clocksource: %s", clockSource.Mode)
}
}
type TimestampConverter func(timestamp uint64) uint64
// Returns a function that converts a CT timestamp from clocksource units into
// seconds.
func NewCTTimeToSecConverter(clockSource *models.ClockSource) (TimestampConverter, error) {
if clockSource == nil {
return nil, fmt.Errorf("clockSource is nil")
}
switch clockSource.Mode {
case models.ClockSourceModeKtime:
converter := func(timestamp uint64) uint64 {
return timestamp
}
return converter, nil
case models.ClockSourceModeJiffies:
hertz := clockSource.Hertz
if hertz == 0 {
return nil, fmt.Errorf("invalid clock Hertz value (0)")
}
converter := func(timestamp uint64) uint64 {
return (timestamp << bpfMonoScaler) / uint64(hertz)
}
return converter, nil
default:
return nil, fmt.Errorf("invalid clocksource: %s", clockSource.Mode)View on GitHub (pinned to ac7b90affa)
Solutions
- Check and propagate the error from GetClockSourceFromAgent before constructing the converter
- Fall back to reading the clocksource from the agent config file when the API returns none
- Never pass a literal nil; validate the models.ClockSource at the call site
Example fix
// before: nil deref risk
clockSource, _ := GetClockSourceFromAgent(svc)
conv, err := NewCTTimeToSecConverter(clockSource)
// after: check error and nil
clockSource, err := GetClockSourceFromAgent(svc)
if err != nil {
return nil, err
}
conv, err := NewCTTimeToSecConverter(clockSource) Defensive patterns
Strategy: validation
Validate before calling
// Guard before constructing the converter
if clockSource == nil {
return errors.New("clocksource must be resolved (API or config) before building converter")
} Type guard
func hasClockSource(cs *models.ClockSource) bool {
return cs != nil && cs.Mode != ""
} Try / catch
// Go: nil-check pattern
clockSource, err := GetClockSourceFromAgent(svc)
if err != nil {
return fmt.Errorf("cannot build time converter: %w", err)
}
conv, err := NewCTTimeToSecConverter(clockSource)
if err != nil {
return err
} Prevention
- Never ignore the error from GetClockSourceFromAgent
- Wire converter construction only after clocksource discovery succeeds
- Avoid literal nil in tests; use a ktime ClockSource stub
- Use nilness-style linters to catch unchecked error paths yielding nil
When it happens
Trigger: Passing nil to NewCTTimeToSecConverter — typically when GetClockSourceFromAgent already failed, an error path was ignored upstream, or a caller hardcodes nil assuming ktime.
Common situations: Ignoring the error from GetClockSourceFromAgent and using the nil result; wiring the converter before the agent health endpoint is available; tests passing nil stubs.
Related errors
- routerID cannot be nil when freeing a specific router ID
- %T is not a pointer to struct
- analyzing fields of %T: %w
- map %s is not a per-CPU map
- lifecycle managed by Dynamic Lifecycle
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/d4102c095f235be4.
Report an issue: GitHub.