hyperledger/fabric · error

failed to marshal config

Error message

failed to marshal config

What it means

batchUpdateDocuments() assembles documentMap["docs"] (the array of per-document maps) and marshals it into the _bulk_docs request body with json.Marshal. Failure is wrapped as 'error marshalling json data' and the batch write is aborted. Since inputs are already decoded into plain maps/slices, failure indicates some document map still contains values Go cannot encode (channels, funcs, cycles, unsupported types).

Source

Thrown at cmd/common/config.go:47

		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,
	}

	for key, value := range nonEmptyElems {
		if value == "" {
			return errors.Errorf("%s is mandatory and cannot be empty", key)
		}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Marshal each document map individually in a loop to isolate the failing key and underlying error
  2. Strip/fix non-serializable values before adding to jsonDocumentMap
  3. Ensure attachments use the proper *Attachment struct, not raw unsupported types
  4. Verify against stock Fabric — the stock pipeline marshals only plain maps/strings/[]byte and should never fail
  5. Add a pre-flight json.Marshal check and skip/log offending documents rather than failing the whole batch

Example fix

// before
documentMap["docs"] = jsonDocumentMap
bulkDocsJSON, err := json.Marshal(documentMap) // fails on one bad doc
// after
for i, doc := range jsonDocumentMap {
    if _, e := json.Marshal(doc); e != nil {
        return nil, fmt.Errorf("document %d not marshallable: %w", i, e)
    }
}
bulkDocsJSON, err := json.Marshal(documentMap)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(documentMap); err != nil {
    return fmt.Errorf("bulk docs payload not marshallable: %w", err)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "error marshalling json data") {
    return fmt.Errorf("_bulk_docs payload invalid — inspect document maps: %w", err)
}

Prevention

When it happens

Trigger: A batch write where one or more per-document maps (or their attachment structures) contain non-encodable values after unmarshal+merge — usually only possible via modified code paths or attachment metadata with unsupported types.

Common situations: Custom attachments handling that inserts unsupported types into the map, forks altering document construction, cyclic references introduced by custom data flowing into the document map.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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