{"record":{"id":"c8b44f4019995607","repo":"hyperledger/fabric","slug":"empty-path-not-allowed","errorCode":null,"errorMessage":"empty path not allowed","messagePattern":"empty path not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/persistence/persistence.go","lineNumber":46,"sourceCode":"// checking for existence of a specified file\ntype IOReadWriter interface {\n\tReadDir(string) ([]os.FileInfo, error)\n\tReadFile(string) ([]byte, error)\n\tRemove(name string) error\n\tWriteFile(string, string, []byte) error\n\tMakeDir(string, os.FileMode) error\n\tExists(path string) (bool, error)\n}\n\n// FilesystemIO is the production implementation of the IOWriter interface\ntype FilesystemIO struct{}\n\n// WriteFile writes a file to the filesystem; it does so atomically\n// by first writing to a temp file and then renaming the file so that\n// if the operation crashes midway we're not stuck with a bad package\nfunc (f *FilesystemIO) WriteFile(path, name string, data []byte) error {\n\tif path == \"\" {\n\t\treturn errors.New(\"empty path not allowed\")\n\t}\n\ttmpFile, err := os.CreateTemp(path, \".ccpackage.\")\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"error creating temp file in directory '%s'\", path)\n\t}\n\tdefer os.Remove(tmpFile.Name())\n\n\tif n, err := tmpFile.Write(data); err != nil || n != len(data) {\n\t\tif err == nil {\n\t\t\terr = errors.Errorf(\n\t\t\t\t\"failed to write the entire content of the file, expected %d, wrote %d\",\n\t\t\t\tlen(data), n,\n\t\t\t)\n\t\t}\n\t\treturn errors.Wrapf(err, \"error writing to temp file '%s'\", tmpFile.Name())\n\t}\n\n\tif err := tmpFile.Close(); err != nil {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/persistence/persistence.go#L28-L64","documentation":"FilesystemIO.WriteFile requires a non-empty base directory path because it creates a temporary file inside that directory (os.CreateTemp) before renaming into place. An empty path would be invalid, so it is rejected up front with this sentinel error.","triggerScenarios":"Invoking WriteFile (directly or via Store.SaveChaincodePackage) with path == \"\", e.g. a store constructed with Store{Path: \"\"} or a persistence config where the chaincode install directory was not set.","commonSituations":"Missing or misparsed configuration for peer.fileSystemPath / chaincode install path; constructing FilesystemIO manually in tests or tooling with an empty Path field.","solutions":["Set the store path explicitly, e.g. NewStore(path) with the peer's fileSystemPath + \"/lifecycle/chaincodes\"","Fix the peer configuration so peer.fileSystemPath is non-empty before instantiating the store","Add a startup validation that the configured path is non-empty and writable"],"exampleFix":"// before\nstore := &persistence.Store{Path: \"\", ReadWriter: &persistence.FilesystemIO{}}\n\n// after\nstore, err := persistence.NewStore(\"/var/hyperledger/production/lifecycle/chaincodes\", &persistence.FilesystemIO{})","handlingStrategy":"validation","validationCode":"func ensurePath(p string) error {\n    if strings.TrimSpace(p) == \"\" {\n        return errors.New(\"chaincode store path must be non-empty\")\n    }\n    return nil\n}","typeGuard":"func validPath(p string) bool { return p != \"\" }","tryCatchPattern":"if err := io.WriteFile(path, name, data); err != nil {\n    if err.Error() == \"empty path not allowed\" {\n        return fmt.Errorf(\"store path not configured: %w\", err)\n    }\n    return err\n}","preventionTips":["Always obtain the store path from peer configuration (peer.fileSystemPath), never hardcode empty defaults","Validate configuration at peer startup, before the store is constructed","In tooling/tests, use NewStore instead of building Store structs by hand"],"tags":["filesystem","config","validation"],"backgroundTag":"missing-env-var","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}