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
- Validate metadata.json with 'jq . metadata.json' or json.Unmarshal in a test; fix syntax errors.
- Ensure it is a JSON object with string fields Type and Label, e.g. {"Type":"cc","Label":"mycc-v1"}.
- Recreate metadata via 'peer lifecycle chaincode package' to get canonical content.
- 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
- Lint metadata.json with 'jq empty' before packaging.
- Use string fields Type and Label, capitalized as the struct expects.
- Generate metadata via 'peer lifecycle chaincode package', not by hand.
- Ensure no error pages/placeholders get saved as metadata.json.
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
- too few arguments
- Failed opening file %s: %v
- config isn't valid
- failed to unmarshal output from 'go list'
- invalid duration
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8c072fe453f7cdb8.
Report an issue: GitHub.