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
- Verify the file path exists and is readable (ls -l / cat the file)
- Use an absolute path to the collections config JSON
- Fix file permissions or mount the file into the container running the peer CLI
- 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
- Use absolute paths for --collections-config
- Cat/validate the JSON file in CI before deploying chaincode
- Mount collection configs explicitly into containers running the peer CLI
- Check file permissions and current working directory before CLI calls
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
- reading config block: %s
- reading config updte envelope: %s
- error encode input
- error writing output
- '%s' not equal <newest|oldest|config|(number)>
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/9219db2487c7d202.
Report an issue: GitHub.