hyperledger/fabric · error

could not unmarshal %s as json

Error message

could not unmarshal %s as json

What it means

When the tar entry named 'metadata.json' is found, ParseChaincodePackage json.Unmarshals its bytes into ChaincodePackageMetadata; failure returns this wrapped error naming MetadataFile. The package structure is valid, but metadata.json content is not the expected JSON shape (type, label fields).

Source

Thrown at core/chaincode/persistence/chaincode_package.go:316

			return ccPackageMetadata, nil, errors.Wrapf(err, "error inspecting next tar header")
		}

		if header.Typeflag != tar.TypeReg {
			return ccPackageMetadata, nil, errors.Errorf("tar entry %s is not a regular file, type %v", header.Name, header.Typeflag)
		}

		fileBytes, err := io.ReadAll(tarReader)
		if err != nil {
			return ccPackageMetadata, nil, errors.Wrapf(err, "could not read %s from tar", header.Name)
		}

		switch header.Name {

		case MetadataFile:
			ccPackageMetadata = &ChaincodePackageMetadata{}
			err := json.Unmarshal(fileBytes, ccPackageMetadata)
			if err != nil {
				return ccPackageMetadata, nil, errors.Wrapf(err, "could not unmarshal %s as json", MetadataFile)
			}

		case CodePackageFile:
			codePackage = fileBytes
		default:
			logger.Warningf("Encountered unexpected file '%s' in top level of chaincode package", header.Name)
		}
	}

	if codePackage == nil {
		return ccPackageMetadata, nil, errors.Errorf("did not find a code package inside the package")
	}

	if ccPackageMetadata == nil {
		return ccPackageMetadata, nil, errors.Errorf("did not find any package metadata (missing %s)", MetadataFile)
	}

	if err := ValidateLabel(ccPackageMetadata.Label); err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Validate metadata.json with 'jq . metadata.json' or json.Unmarshal in a test; fix syntax errors.
  2. Ensure it is a JSON object with string fields Type and Label, e.g. {"Type":"cc","Label":"mycc-v1"}.
  3. Recreate metadata via 'peer lifecycle chaincode package' to get canonical content.
  4. Repackage and reinstall the chaincode with corrected metadata.

Example fix

// before: metadata.json
{"type": "golang", "label": 123}
// after
{"Type": "golang", "Label": "mycc-v1.0"}
Defensive patterns

Strategy: validation

Validate before calling

var md struct {
	Type  string `json:"Type"`
	Label string `json:"Label"`
}
if err := json.Unmarshal(metadataBytes, &md); err != nil {
	return fmt.Errorf("metadata.json must be a JSON object with string Type and Label: %w", err)
}
if md.Type == "" || md.Label == "" {
	return fmt.Errorf("metadata.json Type and Label must be non-empty")
}

Try / catch

if _, _, err := persistence.ParseChaincodePackage(source); err != nil {
	var pe *json.UnmarshalTypeError
	if errors.As(err, &pe) || strings.Contains(err.Error(), "could not unmarshal") {
		return fmt.Errorf("fix metadata.json content (object with Type/Label strings): %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling Parse or PackageID on a package whose metadata.json is empty, contains a JSON array/string instead of an object, has wrong field types (e.g. numeric Type), or is invalid JSON (trailing commas, comments, HTML error pages).

Common situations: Hand-written metadata.json with syntax mistakes, metadata generated with wrong field types, or a placeholder/error page saved as metadata.json.

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/8c072fe453f7cdb8. Report an issue: GitHub.