hyperledger/fabric · error

could not read %s from tar

Error message

could not read %s from tar

What it means

After confirming a tar entry is a regular file, ParseChaincodePackage reads its full contents with io.ReadAll; if that read fails it returns this wrapped error naming the entry. This indicates I/O-level corruption or truncation within an otherwise well-formed tar header.

Source

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

	var codePackage []byte
	var ccPackageMetadata *ChaincodePackageMetadata
	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		}

		if err != nil {
			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)
		}
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Repackage the chaincode and re-upload/install it.
  2. Verify integrity with tar -tzvf (it will report unexpected EOF).
  3. Compare the package checksum with the source of truth.
  4. Check storage/transfer path (network reliability, disk space) that truncated the bytes.

Example fix

// before: partial copy
aws s3 cp s3://bucket/mycc.tgz . --range bytes=0-1000
// after: full object copy
aws s3 cp s3://bucket/mycc.tgz . && sha256sum mycc.tgz
Defensive patterns

Strategy: validation

Validate before calling

gr, _ := gzip.NewReader(bytes.NewReader(source))
tr := tar.NewReader(gr)
for {
	h, err := tr.Next()
	if err == io.EOF { break }
	if err != nil { return err }
	if _, err := io.ReadAll(tr); err != nil {
		return fmt.Errorf("entry %q truncated/corrupt: %w", h.Name, err)
	}
}

Try / catch

meta, code, err := persistence.ParseChaincodePackage(source)
if err != nil {
	if strings.Contains(err.Error(), "could not read") {
		return fmt.Errorf("package truncated in transit; re-upload with checksum check: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling Parse or PackageID where a tar entry's data blocks are truncated or undecodable mid-stream — e.g. the gzip stream ends before the entry's declared size is read.

Common situations: Packages truncated during upload/download, corrupted stored blobs, or archives built by buggy tooling writing short data sections.

Related errors


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