cilium/cilium · error

could not determine clocksource

Error message

could not determine clocksource

What it means

GetClockSourceFromAgent queries the cilium agent's Healthz API endpoint and expects a ClockSource object in the response. When the payload's ClockSource field is nil, the library cannot know which clock the BPF timestamps use, so it refuses to guess and returns this error. It is a defensive check against an agent that did not report its clocksource.

Source

Thrown at pkg/maps/timestamp/timestamp.go:52

}

// Get current clocksource - to be used in the agent context.
func GetClockSourceFromOptions() *models.ClockSource {
	return getClockSourceFromConfig(option.Config)
}

// Connect to the agent via API and get its current clocksource.
func GetClockSourceFromAgent(svc daemon.ClientService) (*models.ClockSource, error) {
	params := daemon.NewGetHealthzParamsWithTimeout(5 * time.Second)
	brief := false
	params.SetBrief(&brief)
	resp, err := svc.GetHealthz(params)
	if err != nil {
		return nil, err
	}

	if resp.Payload.ClockSource == nil {
		return nil, fmt.Errorf("could not determine clocksource")
	}

	return resp.Payload.ClockSource, nil
}

// Get the clocksource from the agent config file in case agent is not running.
func GetClockSourceFromRuntimeConfig() (*models.ClockSource, error) {
	var config option.DaemonConfig

	agentConfigFile := filepath.Join(defaults.RuntimePath, defaults.StateDir,
		"agent-runtime-config.json")

	if byteValue, err := os.ReadFile(agentConfigFile); err == nil {
		err = json.Unmarshal(byteValue, &config)
		if err != nil {
			return nil, err
		}
		return getClockSourceFromConfig(&config), nil

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Upgrade or restart the cilium agent so its health payload includes clock_source
  2. Read the clocksource from the agent config file instead (the package provides a config-file path for exactly this case)
  3. Verify the Healthz response payload actually contains clock_source (inspect GET /healthz output)
  4. Ensure the Go client model (models.ClockSource) matches the agent's API version

Example fix

// before: nil propagates to converter constructors
clockSource, _ := GetClockSourceFromAgent(svc)
// after: fall back to config-file clocksource on nil
resp, err := svc.GetHealthz(params)
if err != nil {
    return nil, err
}
if resp.Payload.ClockSource == nil {
    return getClockSourceFromConfig() // fallback path
}
return resp.Payload.ClockSource, nil
Defensive patterns

Strategy: fallback

Validate before calling

// Check the payload before trusting it
resp, _ := svc.GetHealthz(params)
hasClockSource := resp != nil && resp.Payload != nil && resp.Payload.ClockSource != nil
if !hasClockSource {
    // fall back to agent config file clocksource
}

Type guard

func clockSourceKnown(cs *models.ClockSource) bool {
    return cs != nil && cs.Mode != ""
}

Try / catch

// Go: fall back to config-file source when API yields none
clockSource, err := GetClockSourceFromAgent(svc)
if err != nil {
    clockSource, err = getClockSourceFromConfig()
    if err != nil {
        return fmt.Errorf("no clocksource from API or config: %w", err)
    }
}

Prevention

When it happens

Trigger: Calling GetClockSourceFromAgent against an agent whose /healthz payload has no clock_source field — e.g. an older agent version predating clocksource reporting, a partially initialized agent, or a proxied/mocked health API client returning a stale/empty payload.

Common situations: Version skew between client and agent (old agent without clocksource support); agent still starting up before config is populated; health endpoint behind a proxy that drops optional fields.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/8f39539c73124510. Report an issue: GitHub.