hyperledger/fabric · error

config isn't valid

Error message

config isn't valid

What it means

While preparing a _bulk_docs batch write, batchUpdateDocuments() decodes each CouchDoc's jsonValue payload into a generic map so keys/attachments can be merged. If a document's jsonValue is not valid JSON, json.Unmarshal fails and the error is wrapped as 'error unmarshalling json data', aborting the whole batch update.

Source

Thrown at cmd/common/config.go:43

// ConfigFromFile loads the given file and converts it to a Config
func ConfigFromFile(file string) (Config, error) {
	configData, err := os.ReadFile(file)
	if err != nil {
		return Config{}, errors.WithStack(err)
	}
	config := Config{}

	if err := yaml.Unmarshal(configData, &config); err != nil {
		return Config{}, errors.Errorf("error unmarshalling YAML file %s: %s", file, err)
	}

	return config, validateConfig(config)
}

// ToFile writes the config into a file
func (c Config) ToFile(file string) error {
	if err := validateConfig(c); err != nil {
		return errors.Wrap(err, "config isn't valid")
	}
	b, err := yaml.Marshal(c)
	if err != nil {
		return errors.Wrap(err, "failed to marshal config")
	}
	if err := os.WriteFile(file, b, 0o600); err != nil {
		return errors.Errorf("failed writing file %s: %v", file, err)
	}
	return nil
}

func validateConfig(conf Config) error {
	nonEmptyElems := map[string]string{
		"MSPID":        conf.SignerConfig.MSPID,
		"IdentityPath": conf.SignerConfig.IdentityPath,
		"KeyPath":      conf.SignerConfig.KeyPath,
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Find the offending document: validate each CouchDoc with json.Valid(doc.jsonValue) before batching and log the failing key
  2. Fix the producer of the jsonValue so it writes valid JSON (use json.Marshal on a proper struct)
  3. Inspect the ledger records for that key; if corrupt, rebuild/resync the state database
  4. Check for version mismatches between peer binaries and previously written data
  5. Report upstream if stock Fabric produces this — stock code paths always marshal valid JSON

Example fix

// before
doc := &couchDoc{jsonValue: []byte(rawValue)} // rawValue may be non-JSON
// after
if !json.Valid([]byte(rawValue)) {
    return nil, fmt.Errorf("invalid JSON for key %s", key)
}
doc := &couchDoc{jsonValue: []byte(rawValue)}
Defensive patterns

Strategy: validation

Validate before calling

for _, doc := range documents {
    if len(doc.jsonValue) > 0 && !json.Valid(doc.jsonValue) {
        return fmt.Errorf("couchDoc jsonValue is not valid JSON")
    }
}

Type guard

func validJSONDoc(d *couchDoc) bool {
    return len(d.jsonValue) == 0 || json.Valid(d.jsonValue)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "error unmarshalling json data") {
    return fmt.Errorf("corrupt document in batch — locate and fix producer: %w", err)
}

Prevention

When it happens

Trigger: Any CouchDoc in the batch whose jsonValue bytes are corrupted or non-JSON — typically a bug in code that constructed the CouchDoc (e.g. hand-built documents, custom serialization of state values) or data written by an incompatible version.

Common situations: Forked/patched Fabric writing raw non-JSON values as jsonValue, custom external builders (such as lvcc or custom MSP data) supplying malformed JSON, version upgrades where previously-valid encodings changed, binary data incorrectly stuffed into jsonValue.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/4b450e2dd272571b. Report an issue: GitHub.