hyperledger/fabric · error

only applicable for private data

Error message

only applicable for private data

What it means

This error is returned by the peer's chaincode handler when a chaincode calls a private-data-capable system API (e.g. GetPrivateData, PutPrivateData, GetPrivateDataHash) without specifying a collection name. The collection argument is mandatory because all private data operations are scoped to a specific collection; an empty string means the chaincode invoked the private data API incorrectly. The handler rejects the call before doing any ledger work.

Source

Thrown at core/chaincode/handler.go:1262

	if err := h.purgePrivateData(delState, txContext, msg.ChannelId); err != nil {
		return nil, errors.WithStack(err)
	}

	// Send response msg back to chaincode.
	return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil
}

func (h *Handler) purgePrivateData(msg *pb.DelState, txContext *TransactionContext, channelId string) error {
	err := h.checkPurgePrivateDataCap(channelId)
	if err != nil {
		return err
	}

	namespaceID := txContext.NamespaceID
	collection := msg.Collection
	if collection == "" {
		return errors.New("only applicable for private data")
	}

	if txContext.IsInitTransaction {
		return errors.New("private data APIs are not allowed in chaincode Init()")
	}

	if err = errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil {
		return err
	}

	if err = txContext.TXSimulator.PurgePrivateData(namespaceID, collection, msg.Key); err != nil {
		return errors.WithStack(err)
	}

	return nil
}

func (h *Handler) HandleWriteBatch(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Pass a valid, non-empty collection name defined in the chaincode's collection configuration as the first argument to the private data API
  2. Check the invoke args order: GetPrivateData(collection, key) — ensure the collection is args[0] and was supplied by the client
  3. Verify the client proposal inputs actually include the collection name (log args before the call)

Example fix

// before
value, err := stub.GetPrivateData(collectionArg, key) // collectionArg == ""

// after
if collectionArg == "" {
	return shim.Error("collection name must be provided")
}
value, err := stub.GetPrivateData("collectionOK", key)
Defensive patterns

Strategy: validation

Validate before calling

func validatePrivateDataCall(collection string) error {
	if collection == "" {
		return fmt.Errorf("collection name required for private data API")
	}
	return nil
}
// call before stub.GetPrivateData(collection, key)

Try / catch

resp, err := stub.GetPrivateData(collection, key)
if err != nil {
	if strings.Contains(err.Error(), "only applicable for private data") {
		return shim.Error("empty collection passed to private data API")
	}
	return shim.Error(err.Error())
}

Prevention

When it happens

Trigger: Calling a private data API such as ctx.GetStub().GetPrivateData(...) or PutPrivateData(...) with an empty collection name — e.g. passing an unbound/empty variable or using the public-state API shape on the private-data handler path (GetStateAsBytes-style calls routed through the private data message handler without msg.Collection set).

Common situations: Chaincode code that reads the collection name from a key or parameter that is empty at runtime; calling GetPrivateData with args[0] unset in the invoke arguments; copy-paste from public GetState where collection was later added but never populated; mixing up GetState and GetPrivateData signatures.

Related errors


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