crowdsecurity/crowdsec · error

can't read aws_config_dir %s got err %w

Error message

can't read aws_config_dir %s got err %w 

What it means

The cloudwatch acquisition source validates that the optional aws_config_dir exists and is stat-able before wiring AWS SDK env vars (AWS_SDK_LOAD_CONFIG, AWS_CONFIG_FILE, AWS_SHARED_CREDENTIALS_FILE). If os.Stat fails (missing directory, typo, permission issue), setupAWS returns this wrapped error.

Source

Thrown at pkg/acquisition/modules/cloudwatch/config.go:161

	s.logger.Tracef("describelogstreams_limit set to %d", *s.Config.DescribeLogStreamsLimit)
	s.logger.Tracef("poll_new_stream_interval set to %v", *s.Config.PollNewStreamInterval)
	s.logger.Tracef("max_stream_age set to %v", *s.Config.MaxStreamAge)
	s.logger.Tracef("poll_stream_interval set to %v", *s.Config.PollStreamInterval)
	s.logger.Tracef("stream_read_timeout set to %v", *s.Config.StreamReadTimeout)
	s.logger.Tracef("getlogeventspages_limit set to %v", *s.Config.GetLogEventsPagesLimit)
	s.logger.Tracef("aws_api_timeout set to %v", *s.Config.AwsApiCallTimeout)
	s.logger.Tracef("aws_config_dir set to %s", *s.Config.AwsConfigDir)

	return s.setupAWS(ctx)
}


func (s *Source) setupAWS(ctx context.Context) error {
	if *s.Config.AwsConfigDir != "" {
		_, err := os.Stat(*s.Config.AwsConfigDir)
		if err != nil {
			s.logger.Errorf("can't read aws_config_dir '%s' got err %s", *s.Config.AwsConfigDir, err)
			return fmt.Errorf("can't read aws_config_dir %s got err %w ", *s.Config.AwsConfigDir, err)
		}

		os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
		// as aws sdk relies on $HOME, let's allow the user to override it :)
		os.Setenv("AWS_CONFIG_FILE", fmt.Sprintf("%s/config", *s.Config.AwsConfigDir))
		os.Setenv("AWS_SHARED_CREDENTIALS_FILE", fmt.Sprintf("%s/credentials", *s.Config.AwsConfigDir))
	} else {
		if s.Config.AwsRegion == "" {
			s.logger.Errorf("aws_region is not specified, specify it or aws_config_dir")
			return errors.New("aws_region is not specified, specify it or aws_config_dir")
		}

		os.Setenv("AWS_REGION", s.Config.AwsRegion)
	}

	if err := s.newClient(ctx); err != nil {
		return err
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Create the directory or fix the path in the acquisition config (aws_config_dir).
  2. Ensure the crowdsec process user has read/execute permission on the directory.
  3. If no custom AWS config is needed, drop aws_config_dir from the source config so defaults are used.
  4. Mount the AWS config directory into the container when running under Docker/Kubernetes.

Example fix

// before (acquis.yaml)
source: cloudwatch
aws_config_dir: /etc/crowdsec/awscfg  # does not exist
// after
sudo mkdir -p /etc/crowdsec/awscfg && cp ~/.aws/{config,credentials} /etc/crowdsec/awscfg/
Defensive patterns

Strategy: validation

Validate before calling

if *cfg.AwsConfigDir != "" {
    if info, err := os.Stat(*cfg.AwsConfigDir); err != nil || !info.IsDir() {
        return fmt.Errorf("aws_config_dir %q missing or not a directory", *cfg.AwsConfigDir)
    }
}

Try / catch

if err := src.Configure(ctx, cfg); err != nil {
    return fmt.Errorf("cloudwatch source setup failed: %w", err)
}

Prevention

When it happens

Trigger: Configure/ConfigureByDSN creating a cloudwatch source with aws_config_dir set to a path that does not exist or is unreadable; os.Stat fails with ENOENT/EACCES and the error is wrapped into this message.

Common situations: Typo in the aws_config_dir path, pointing at a file instead of a directory tree, permissions restricted for the crowdsec service user, or the directory living inside a container image that wasn't mounted.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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