{"record":{"id":"b877e550a17ed9dd","repo":"crowdsecurity/crowdsec","slug":"failed-to-serialize-last-timestamp-w","errorCode":null,"errorMessage":"failed to serialize last timestamp: %w","messagePattern":"failed to serialize last timestamp: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiserver/papi.go","lineNumber":251,"sourceCode":"\treturn nil\n}\n\n// Pull is the long polling client for real-time decisions from PAPI\nfunc (p *Papi) Pull(ctx context.Context) error {\n\tp.Logger.Infof(\"Starting Polling API Pull\")\n\n\tlastTimestamp := time.Time{}\n\n\tlastTimestampStr, err := p.DBClient.GetConfigItem(ctx, PapiPullKey)\n\tif err != nil {\n\t\tp.Logger.Warningf(\"failed to get last timestamp for papi pull: %s\", err)\n\t}\n\n\t// value doesn't exist, it's first time we're pulling\n\tif lastTimestampStr == \"\" {\n\t\tbinTime, err := lastTimestamp.MarshalText()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to serialize last timestamp: %w\", err)\n\t\t}\n\n\t\tif err := p.DBClient.SetConfigItem(ctx, PapiPullKey, string(binTime)); err != nil {\n\t\t\tp.Logger.Errorf(\"error setting papi pull last key: %s\", err)\n\t\t} else {\n\t\t\tp.Logger.Debugf(\"config item '%s' set in database with value '%s'\", PapiPullKey, string(binTime))\n\t\t}\n\t} else {\n\t\tif err := lastTimestamp.UnmarshalText([]byte(lastTimestampStr)); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to parse last timestamp: %w\", err)\n\t\t}\n\t}\n\n\ttokenRefreshChan := p.apiClient.GetTokenRefreshChan()\n\tvar papiChan chan longpollclient.Event // Chan is nil by default to block until PAPI actually establishes the connection\n\tpapiCtx, cancel := context.WithCancel(ctx)\n\n\tcurrentSubscriptionType := p.apiClient.GetSubscriptionType()","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/papi.go#L233-L269","documentation":"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.","triggerScenarios":"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.","commonSituations":"System clock set far in the future or past in a container/VM, corrupted time source, or running with a fabricated time in tests.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if lastTimestamp.Year() < 1 || lastTimestamp.Year() > 9999 { return fmt.Errorf(\"lastTimestamp out of range: %v\", lastTimestamp) }","typeGuard":null,"tryCatchPattern":"if err := p.Pull(ctx); err != nil { if strings.Contains(err.Error(), \"failed to serialize last timestamp\") { log.Error(\"clock anomaly; check system time\"); } }","preventionTips":["Run NTP time sync on hosts and containers","Validate system clock at service startup","Avoid manually fabricating time values in tests"],"tags":["time","papi","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}