{"record":{"id":"19210f2e724c0d9d","repo":"SigNoz/signoz","slug":"errcodetokenolderlastobservedat","errorCode":"ErrCodeTokenOlderLastObservedAt","errorMessage":"last observed at is before the current last observed at","messagePattern":"last observed at is before the current last observed at","errorType":"error_code","errorClass":"errors SigNozError","httpStatus":400,"severity":"warning","filePath":"pkg/types/authtypes/token.go","lineNumber":207,"sourceCode":"\ttyp.RotatedAt = time.Now()\n\n\t// Set the updated at time.\n\ttyp.UpdatedAt = time.Now()\n\n\treturn nil\n}\n\nfunc (typ *Token) RotationAt(rotationInterval time.Duration) time.Time {\n\tif typ.RotatedAt.IsZero() {\n\t\treturn typ.CreatedAt.Add(rotationInterval)\n\t}\n\n\treturn typ.RotatedAt.Add(rotationInterval)\n}\n\nfunc (typ *Token) UpdateLastObservedAt(lastObservedAt time.Time) error {\n\tif lastObservedAt.Before(typ.LastObservedAt) {\n\t\treturn errors.New(errors.TypeInvalidInput, ErrCodeTokenOlderLastObservedAt, \"last observed at is before the current last observed at\")\n\t}\n\n\ttyp.LastObservedAt = lastObservedAt\n\ttyp.UpdatedAt = time.Now()\n\n\treturn nil\n}\n\nfunc (typ Token) MarshalBinary() ([]byte, error) {\n\treturn json.Marshal(typ)\n}\n\nfunc (typ *Token) UnmarshalBinary(data []byte) error {\n\treturn json.Unmarshal(data, typ)\n}\n\ntype TokenStore interface {\n\t// Create a new token.","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/types/authtypes/token.go#L189-L225","documentation":"Returned by Token.UpdateLastObservedAt when the supplied timestamp is older than the token's current LastObservedAt. Last-observed timestamps must be monotonic to keep idle-expiry correct.","triggerScenarios":"Calling UpdateLastObservedAt with an out-of-order timestamp, e.g. from replayed events, clock skew between nodes, or processing requests in the wrong order.","commonSituations":"Distributed workers updating the same token with skewed clocks, or queued/delayed events delivering older observation times.","solutions":["Only send timestamps that are >= the stored LastObservedAt (use server 'now' rather than client timestamps)","If caused by clock skew, sync node clocks (NTP) or stamp server-side time","Ignore/skip this error for stale duplicate updates instead of retrying them"],"exampleFix":"// before\ntoken.UpdateLastObservedAt(clientRequestTime) // may be older\n// after\nnow := time.Now()\nif now.After(token.LastObservedAt) {\n    token.UpdateLastObservedAt(now)\n}","handlingStrategy":"try-catch","validationCode":"if !lastObservedAt.Before(tok.LastObservedAt) {\n    _ = tok.UpdateLastObservedAt(lastObservedAt)\n}","typeGuard":null,"tryCatchPattern":"if err := tok.UpdateLastObservedAt(ts); err != nil {\n    if strings.Contains(err.Error(), \"before the current last observed at\") {\n        return nil // stale update, ignore\n    }\n    return err\n}","preventionTips":["Stamp server time.Now() instead of client-provided timestamps","Sync clocks with NTP across nodes","Treat stale observation updates as no-ops"],"tags":["tokens","auth","monotonic","clock-skew"],"backgroundTag":"out-of-order-timestamp","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}