{"record":{"id":"fac8d7d7599fe7f2","repo":"crowdsecurity/crowdsec","slug":"unable-to-parse-jwt-expiration-w-fac8d7","errorCode":null,"errorMessage":"unable to parse jwt expiration: %w","messagePattern":"unable to parse jwt expiration: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiserver/apic.go","lineNumber":285,"sourceCode":"\n\tscenarios, err := a.FetchScenariosListFromDB(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get scenario in db: %w\", err)\n\t}\n\n\tpassword := strfmt.Password(config.Credentials.Password)\n\n\tauthResp, _, err := a.apiClient.Auth.AuthenticateWatcher(ctx, models.WatcherAuthRequest{\n\t\tMachineID: &config.Credentials.Login,\n\t\tPassword:  &password,\n\t\tScenarios: scenarios,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"authenticate watcher (%s): %w\", config.Credentials.Login, err)\n\t}\n\n\tif err = transport.Expiration.UnmarshalText([]byte(authResp.Expire)); err != nil {\n\t\treturn fmt.Errorf(\"unable to parse jwt expiration: %w\", err)\n\t}\n\n\ttransport.Token = authResp.Token\n\n\treturn a.dbClient.SaveAPICToken(ctx, authResp.Token)\n}\n\n// keep track of all alerts in cache and push it to CAPI every PushInterval.\nfunc (a *apic) Push(ctx context.Context) error {\n\tvar cache modelscapi.AddSignalsRequest\n\n\tticker := time.NewTicker(a.pushIntervalFirst)\n\n\tlog.Infof(\"Start push to CrowdSec Central API (interval: %s once, then %s)\", a.pushIntervalFirst.Round(time.Second), a.pushInterval)\n\n\tfor {\n\t\tselect {\n\t\tcase <-a.pushTomb.Dying(): // if one apic routine is dying, do we kill the others?","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/apic.go#L267-L303","documentation":"The CAPI authentication succeeded but the token expiration timestamp returned in authResp.Expire could not be parsed into a time.Time via transport.Expiration.UnmarshalText. The Central API returned a missing or malformed expiry string, so the client cannot know when to re-authenticate.","triggerScenarios":"Thrown at pkg/apiserver/apic.go:285 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry — a malformed Expire field from CAPI is often transient and fixed by a fresh authentication round","Upgrade crowdsec: newer releases tolerate more expiry formats","If persistent, capture the raw auth response and report it — it indicates a Central API contract change"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}