crowdsecurity/crowdsec · error
failed to serialize last timestamp: %w
Error message
failed to serialize last timestamp: %w
What it means
Pull serializes the starting timestamp with MarshalText before storing it as the PapiPullKey config item on the first pull. This error means the time.Time value could not be marshaled to text — practically unexpected since time.Time always marshals, so it signals an internal/clock anomaly.
Source
Thrown at pkg/apiserver/papi.go:251
return nil
}
// Pull is the long polling client for real-time decisions from PAPI
func (p *Papi) Pull(ctx context.Context) error {
p.Logger.Infof("Starting Polling API Pull")
lastTimestamp := time.Time{}
lastTimestampStr, err := p.DBClient.GetConfigItem(ctx, PapiPullKey)
if err != nil {
p.Logger.Warningf("failed to get last timestamp for papi pull: %s", err)
}
// value doesn't exist, it's first time we're pulling
if lastTimestampStr == "" {
binTime, err := lastTimestamp.MarshalText()
if err != nil {
return fmt.Errorf("failed to serialize last timestamp: %w", err)
}
if err := p.DBClient.SetConfigItem(ctx, PapiPullKey, string(binTime)); err != nil {
p.Logger.Errorf("error setting papi pull last key: %s", err)
} else {
p.Logger.Debugf("config item '%s' set in database with value '%s'", PapiPullKey, string(binTime))
}
} else {
if err := lastTimestamp.UnmarshalText([]byte(lastTimestampStr)); err != nil {
return fmt.Errorf("failed to parse last timestamp: %w", err)
}
}
tokenRefreshChan := p.apiClient.GetTokenRefreshChan()
var papiChan chan longpollclient.Event // Chan is nil by default to block until PAPI actually establishes the connection
papiCtx, cancel := context.WithCancel(ctx)
currentSubscriptionType := p.apiClient.GetSubscriptionType()View on GitHub (pinned to 909b515798)
Solutions
- Fix the system clock (NTP sync) and restart crowdsec
- Delete the stored PapiPullKey config item and let Pull reinitialize
- Verify the host/container time configuration
Defensive patterns
Strategy: validation
Validate before calling
if lastTimestamp.Year() < 1 || lastTimestamp.Year() > 9999 { return fmt.Errorf("lastTimestamp out of range: %v", lastTimestamp) } Try / catch
if err := p.Pull(ctx); err != nil { if strings.Contains(err.Error(), "failed to serialize last timestamp") { log.Error("clock anomaly; check system time"); } } Prevention
- Run NTP time sync on hosts and containers
- Validate system clock at service startup
- Avoid manually fabricating time values in tests
When it happens
Trigger: First-time pull (no stored PapiPullKey value) and lastTimestamp.MarshalText() returns an error, e.g. a time value outside the representable range (year overflow) coming from the system clock.
Common situations: System clock set far in the future or past in a container/VM, corrupted time source, or running with a fabricated time in tests.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- failed to parse last timestamp: %w
- no header in message, skipping
- no source user in header message, skipping
- unable to parse time
- unable to serialize
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b877e550a17ed9dd.
Report an issue: GitHub.