hyperledger/fabric · error

connection.json not found in source folder: %s

Error message

connection.json not found in source folder: %s

What it means

batchRetrieveDocumentMetadata() builds the {"keys": [...]} request body with json.Marshal before POSTing to _all_docs. If marshalling fails the error is wrapped as 'error marshalling json data' and the batch read fails. json.Marshal of a []string of keys can only fail in exotic conditions (keys derived from unsupported types); this typically points to a bug in key construction rather than CouchDB.

Source

Thrown at ccaas_builder/cmd/release/main.go:71

	builderOutputDir, releaseDir := os.Args[1], os.Args[2]
	connectionSrcFile := filepath.Join(builderOutputDir, "/connection.json")

	connectionDir := filepath.Join(releaseDir, "chaincode/server/")
	connectionDestFile := filepath.Join(releaseDir, "chaincode/server/connection.json")

	metadataDir := filepath.Join(builderOutputDir, "META-INF/statedb")
	metadataDestDir := filepath.Join(releaseDir, "statedb")
	if _, err := os.Stat(metadataDir); !os.IsNotExist(err) {
		if err := copy.Copy(metadataDir, metadataDestDir); err != nil {
			return fmt.Errorf("failed to copy metadataDir directory folder: %s", err)
		}
	}

	// Process and update the connections file
	_, err := os.Stat(connectionSrcFile)
	if err != nil {
		return fmt.Errorf("connection.json not found in source folder: %s", err)
	}

	err = os.MkdirAll(connectionDir, 0o750)
	if err != nil {
		return fmt.Errorf("failed to create target folder for connection.json: %s", err)
	}

	if err = Copy(connectionSrcFile, connectionDestFile); err != nil {
		return err
	}

	return nil
}

// Copy the src file to dst. Any existing file will be overwritten and will not
// copy file attributes.
func Copy(src, dst string) error {
	in, err := os.Open(src)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Confirm keys is a []string with plain string content; log the slice before marshalling
  2. If keys come from a custom serializer, verify they decode as valid UTF-8 strings
  3. Reproduce the underlying json.Marshal error directly on the keymap to see the exact unsupported type
  4. Revert or fix any fork modifications to batchRetrieveDocumentMetadata
  5. Upgrade to an unmodified Fabric release for this code path

Example fix

// before
keymap["keys"] = interfaceSliceOfUnknownTypes // may contain unsupported values
// after
keys := make([]string, 0, len(rawKeys))
for _, k := range rawKeys {
    keys = append(keys, fmt.Sprintf("%v", k)) // force plain strings
}
keymap["keys"] = keys
Defensive patterns

Strategy: validation

Validate before calling

for i, k := range keys {
    if k == "" || !utf8.ValidString(k) {
        return fmt.Errorf("invalid key at index %d", i)
    }
}
if _, err := json.Marshal(map[string]any{"keys": keys}); err != nil {
    return err
}

Type guard

func allStrings(v []any) bool {
    for _, x := range v {
        if _, ok := x.(string); !ok { return false }
    }
    return true
}

Try / catch

if err != nil && strings.Contains(err.Error(), "error marshalling json data") {
    return fmt.Errorf("batch keys not marshallable — check key construction: %w", err)
}

Prevention

When it happens

Trigger: Calling BatchRetrieveDocumentMetadata with keys whose marshalling fails — e.g. keys slice containing non-encodable values due to upstream type corruption, or a custom build where keymap gained non-string entries.

Common situations: Extremely rare in stock Fabric; seen in forks/patches that widen the keys parameter type, or instrumentation that inserts unsupported values into the keymap.

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/18786031a2d7ec1e. Report an issue: GitHub.