{"record":{"id":"fb3ed61d77aa3819","repo":"crowdsecurity/crowdsec","slug":"while-reading-s-s-w","errorCode":null,"errorMessage":"while reading %s/%s: %w","messagePattern":"while reading (.+?)/(.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/acquisition/modules/cloudwatch/run.go","lineNumber":309,"sourceCode":"\tstreamIndexMutex.Unlock()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ticker.C:\n\t\t\tp := cloudwatchlogs.NewGetLogEventsPaginator(\n\t\t\t\ts.cwClient,\n\t\t\t\t&cloudwatchlogs.GetLogEventsInput{\n\t\t\t\t\tLimit:         aws.Int32(cfg.GetLogEventsPagesLimit),\n\t\t\t\t\tLogGroupName:  aws.String(cfg.GroupName),\n\t\t\t\t\tLogStreamName: aws.String(cfg.StreamName),\n\t\t\t\t\tNextToken:     startFrom,   // if set, StartFromHead is ignored by AWS\n\t\t\t\t\tStartFromHead: aws.Bool(true),\n\t\t\t\t},\n\t\t\t\t)\n\t\t\tfor p.HasMorePages() {\n\t\t\t\tpage, err := p.NextPage(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\tnewerr := fmt.Errorf(\"while reading %s/%s: %w\", cfg.GroupName, cfg.StreamName, err)\n\t\t\t\t\tcfg.logger.Warningf(\"err: %s\", newerr)\n\n\t\t\t\t\treturn newerr\n\t\t\t\t}\n\n\t\t\t\t// Update token/index\n\t\t\t\tstartFrom = page.NextForwardToken\n\t\t\t\tif startFrom != nil {\n\t\t\t\t\tstreamIndexMutex.Lock()\n\t\t\t\t\ts.streamIndexes[cfg.GroupName+\"+\"+cfg.StreamName] = *startFrom\n\t\t\t\t\tstreamIndexMutex.Unlock()\n\t\t\t\t}\n\n\t\t\t\tif len(page.Events) > 0 {\n\t\t\t\t\tlastReadMessage = time.Now().UTC()\n\t\t\t\t}\n\n\t\t\t\tfor _, ev := range page.Events {","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/cloudwatch/run.go#L291-L327","documentation":"TailLogStream paginates GetLogEvents with StartFromHead to follow a stream. When a page fetch fails the error is wrapped as `while reading <group>/<stream>: <err>`, logged as a warning by the stream's logger, and returned, terminating that stream's tailing goroutine.","triggerScenarios":"TailLogStream's p.NextPage(ctx) fails: expired/invalid nextToken after stream or group deletion, throttling, network outage, or IAM missing logs:GetLogEvents.","commonSituations":"Log stream deleted while being tailed; AWS throttling during bursts; network partition on a long-lived tail; credentials rotated and revoked.","solutions":["Verify the log group and stream still exist in the AWS console or with `aws logs describe-log-streams`","Check IAM permissions for logs:GetLogEvents","Retry on transient errors — restart crowdsec or rely on acquisition reconfiguration; investigate the wrapped AWS error code for throttling","Check network connectivity/VPN to the AWS endpoint"],"exampleFix":"// before\ncloudwatch://my-group?log_stream=deleted-stream\n// after — verify stream exists, or point to an active stream\ncloudwatch://my-group?log_stream=active-stream","handlingStrategy":"retry","validationCode":"_, err := client.DescribeLogStreams(ctx, &cwlogs.DescribeLogStreamsInput{\n    LogGroupName: aws.String(group), LogStreamNamePrefix: aws.String(stream),\n})\nif err != nil { return fmt.Errorf(\"stream %s/%s not reachable: %w\", group, stream, err) }","typeGuard":null,"tryCatchPattern":"page, err := p.NextPage(ctx)\nif err != nil {\n    if isTransient(err) { time.Sleep(backoff); /* re-tail from saved token */ continue }\n    return err\n}","preventionTips":["Persist the last event token so tails can resume after errors","Alert on stream/group deletion if names are dynamic","Grant logs:GetLogEvents and logs:DescribeLogStreams","Back off on ThrottlingException instead of tight-looping"],"tags":["aws","cloudwatch","network","streaming"],"backgroundTag":"api-request-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}