getsops/sops · error

could not read config file: %s

Error message

could not read config file: %s

What it means

loadConfigFile wraps any error returned by os.ReadFile when the sops config file cannot be read from disk. This is a pre-parse failure: the file is missing, unreadable, or the path is a directory. sops aborts config loading because no rules can be evaluated without the file contents.

Source

Thrown at config/config.go:456

		if err != nil {
			return nil, err
		}
		vaultKeys, err := hcvault.NewMasterKeysFromURIs(strings.Join(vaultKeyUris, ","))
		if err != nil {
			return nil, err
		}
		for _, k := range vaultKeys {
			keyGroup = append(keyGroup, k)
		}
		groups = append(groups, keyGroup)
	}
	return groups, nil
}

func loadConfigFile(confPath string) (*configFile, error) {
	confBytes, err := os.ReadFile(confPath)
	if err != nil {
		return nil, fmt.Errorf("could not read config file: %s", err)
	}
	conf := &configFile{}
	conf.Stores = *NewStoresConfig()
	err = conf.load(confBytes)
	if err != nil {
		return nil, fmt.Errorf("error loading config: %s", err)
	}
	return conf, nil
}

func configFromRule(rule *creationRule, kmsEncryptionContext map[string]*string) (*Config, error) {
	cryptRuleCount := 0
	if rule.UnencryptedSuffix != "" {
		cryptRuleCount++
	}
	if rule.EncryptedSuffix != "" {
		cryptRuleCount++
	}

View on GitHub (pinned to 13442bb981)

Solutions

  1. Verify the config path exists and is a regular file before running sops: ls -la <path>
  2. Run sops from the directory containing .sops.yaml (or use --config with an absolute path)
  3. Fix file permissions so the invoking user can read the file (chmod/chown)
  4. If no config is needed, remove the --config flag or ensure creation rules are passed another way

Example fix

// before
sops --config ./conf/sops.yaml encrypt file.yaml
// after
sops --config $(pwd)/.sops.yaml encrypt file.yaml  # path exists and is absolute
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(confPath)
if err != nil {
    return fmt.Errorf("config not accessible at %s: %w", confPath, err)
}
if info.IsDir() {
    return fmt.Errorf("%s is a directory, not a config file", confPath)
}

Try / catch

groups, err := loadConfigFile(confPath)
if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && os.IsNotExist(perr) {
        // fall back to defaults or create a template config
    }
    return err
}

Prevention

When it happens

Trigger: Calling sops with a --config path that does not exist, the default .sops.yaml is absent in a repo where config loading is attempted, or the process lacks read permission on the file.

Common situations: Running sops from a different working directory than the repo root; CI checkouts missing dotfiles; typo in --config flag; file permissions restricted by umask or CI user.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/2ac76064cdb9f8cc. Report an issue: GitHub.