hyperledger/fabric · error

could not read file '%s'

Error message

could not read file '%s'

What it means

GetCollectionConfigFromFile reads the private data collection configuration JSON from disk with os.ReadFile and wraps any read failure as "could not read file '%s'". The file must contain a JSON array of collectionConfigJson elements.

Source

Thrown at internal/peer/chaincode/common.go:170

type collectionConfigJson struct {
	Name              string             `json:"name"`
	Policy            string             `json:"policy"`
	RequiredPeerCount *int32             `json:"requiredPeerCount"`
	MaxPeerCount      *int32             `json:"maxPeerCount"`
	BlockToLive       uint64             `json:"blockToLive"`
	MemberOnlyRead    bool               `json:"memberOnlyRead"`
	MemberOnlyWrite   bool               `json:"memberOnlyWrite"`
	EndorsementPolicy *endorsementPolicy `json:"endorsementPolicy,omitempty"`
}

// GetCollectionConfigFromFile retrieves the collection configuration
// from the supplied file; the supplied file must contain a
// json-formatted array of collectionConfigJson elements
func GetCollectionConfigFromFile(ccFile string) (*pb.CollectionConfigPackage, []byte, error) {
	fileBytes, err := os.ReadFile(ccFile)
	if err != nil {
		return nil, nil, errors.Wrapf(err, "could not read file '%s'", ccFile)
	}

	return getCollectionConfigFromBytes(fileBytes)
}

// getCollectionConfigFromBytes retrieves the collection configuration
// from the supplied byte array; the byte array must contain a
// json-formatted array of collectionConfigJson elements
func getCollectionConfigFromBytes(cconfBytes []byte) (*pb.CollectionConfigPackage, []byte, error) {
	cconf := &[]collectionConfigJson{}
	err := json.Unmarshal(cconfBytes, cconf)
	if err != nil {
		return nil, nil, errors.Wrap(err, "could not parse the collection configuration")
	}

	ccarray := make([]*pb.CollectionConfig, 0, len(*cconf))
	for _, cconfitem := range *cconf {
		p, err := policydsl.FromString(cconfitem.Policy)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the file path exists and is readable (ls -l / cat the file)
  2. Use an absolute path to the collections config JSON
  3. Fix file permissions or mount the file into the container running the peer CLI
  4. Validate the JSON structure: an array of collection configs with name, policy, requiredPeerCount etc.

Example fix

// before
peer chaincode approveformyorg ... --collections-config collections.json
// after
peer chaincode approveformyorg ... --collections-config /absolute/path/collections.json
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function assertCollectionsConfig(p) {
  const cfg = JSON.parse(fs.readFileSync(p, 'utf8'));
  if (!Array.isArray(cfg)) throw new Error('collections config must be a JSON array');
  if (cfg.length === 0) throw new Error('collections config array is empty');
}
assertCollectionsConfig('/absolute/path/collections.json');

Try / catch

cfg, sig, err := GetCollectionConfigFromFile(path)
if err != nil {
  return fmt.Errorf("collections config: %w", err) // includes could not read file '%s'
}

Prevention

When it happens

Trigger: peer chaincode approveformyorg/commit invoked with --collections-config pointing to a nonexistent, unreadable, or path-mistyped file.

Common situations: Wrong path/typo, file not mounted into a container where the peer CLI runs, permission errors, running CLI from a different working directory than expected.

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 hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/9219db2487c7d202. Report an issue: GitHub.