crowdsecurity/crowdsec · error

failed to read header of object %s/%s: %w

Error message

failed to read header of object %s/%s: %w

What it means

For keys ending in .gz, readFile reads a 2-byte header from the object body to detect gzip magic bytes. If the read fails (body errored, truncated, or already consumed), this wrapped error is returned.

Source

Thrown at pkg/acquisition/modules/s3/run.go:363

		"key":    key,
	})

	output, err := s.s3Client.GetObject(s.ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	})
	if err != nil {
		return fmt.Errorf("failed to get object %s/%s: %w", bucket, key, err)
	}
	defer output.Body.Close()

	if strings.HasSuffix(key, ".gz") {
		// This *might* be a gzipped file, but sometimes the SDK will decompress the data for us (it's not clear when it happens, only had the issue with cloudtrail logs)
		header := make([]byte, 2)

		_, err := output.Body.Read(header)
		if err != nil {
			return fmt.Errorf("failed to read header of object %s/%s: %w", bucket, key, err)
		}

		if header[0] == 0x1f && header[1] == 0x8b {
			gz, err := gzip.NewReader(io.MultiReader(bytes.NewReader(header), output.Body))
			if err != nil {
				return fmt.Errorf("failed to create gzip reader for object %s/%s: %w", bucket, key, err)
			}
			scanner = bufio.NewScanner(gz)
		} else {
			scanner = bufio.NewScanner(io.MultiReader(bytes.NewReader(header), output.Body))
		}
	} else {
		scanner = bufio.NewScanner(output.Body)
	}

	if s.Config.MaxBufferSize > 0 {
		s.logger.Infof("Setting max buffer size to %d", s.Config.MaxBufferSize)

View on GitHub (pinned to 909b515798)

Solutions

  1. Retry acquisition; transient network errors usually resolve.
  2. Check the object is a valid, non-empty file.
  3. Verify stable connectivity to the S3 endpoint; check proxy/MinIO logs for truncation.
Defensive patterns

Strategy: retry

Validate before calling

// ensure the object is non-empty before reading
head, err := client.HeadObject(ctx, &s3.HeadObjectInput{Bucket: &b, Key: &k})
if err == nil && (head.ContentLength == nil || *head.ContentLength == 0) {
    return fmt.Errorf("object %s/%s is empty", b, k)
}

Try / catch

if err := readFile(bucket, key); err != nil && strings.Contains(err.Error(), "failed to read header") {
    // transient IO problem: requeue with backoff
}

Prevention

When it happens

Trigger: The GetObject response body returns an error on Read: interrupted connection, streaming body closed early, or an empty/zero-byte object named *.gz.

Common situations: Network interruptions mid-stream; zero-byte .gz placeholder objects uploaded by producers; proxies/MinIO endpoints cutting the response short.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/47306a4b49928502. Report an issue: GitHub.