hyperledger/fabric · critical
failed to restore working directory: %s
Error message
failed to restore working directory: %s
What it means
moduleInfo chdirs into the chaincode path and defers a restore of the original working directory; if the restore chdir fails, it panics with 'failed to restore working directory: %s'. This is a hard safety failure to avoid leaving the process in the wrong directory.
Source
Thrown at core/chaincode/platforms/golang/platform.go:389
return false, err
default:
return fi.Mode().IsRegular(), nil
}
}
func moduleInfo(path string) (*ModuleInfo, error) {
entryWD, err := os.Getwd()
if err != nil {
return nil, errors.Wrap(err, "failed to get working directory")
}
// directory doesn't exist so unlikely to be a module
if err := os.Chdir(path); err != nil {
return nil, nil
}
defer func() {
if err := os.Chdir(entryWD); err != nil {
panic(fmt.Sprintf("failed to restore working directory: %s", err))
}
}()
// Using `go list -m -f '{{ if .Main }}{{.GoMod}}{{ end }}' all` may try to
// generate a go.mod when a vendor tool is in use. To avoid that behavior
// we use `go env GOMOD` followed by an existence check.
cmd := exec.Command("go", "env", "GOMOD")
cmd.Env = os.Environ()
output, err := cmd.Output()
if err != nil {
return nil, wrapExitErr(err, "failed to determine module root")
}
modExists, err := regularFileExists(strings.TrimSpace(string(output)))
if err != nil {
return nil, err
}
if !modExists {View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the peer's original working directory remains mounted and exists during chaincode packaging.
- Avoid deleting temp/mount directories concurrently with packaging operations.
- Run the peer from a stable directory (e.g. /etc/hyperledger/fabric) rather than ephemeral paths.
Defensive patterns
Strategy: try-catch
Validate before calling
wd, err := os.Getwd()
if err != nil { return err }
if _, err := os.Stat(wd); err != nil { return fmt.Errorf("cwd will be unchdir-able: %w", err) } Try / catch
// moduleInfo panics on restore failure; guard at a higher level
func safeDescribe(path string) (out *golang.CodeDescriptor, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("moduleInfo panic: %v", r)
}
}()
return golang.DescribeCode(path)
} Prevention
- Run the peer from a stable directory like /etc/hyperledger/fabric
- Avoid concurrent tmp-dir cleanup during packaging
- Keep mounts serving the peer's cwd alive for the process lifetime
When it happens
Trigger: The entry working directory captured by os.Getwd is deleted or becomes inaccessible while moduleInfo is executing inside the chaincode path, so the deferred os.Chdir(entryWD) fails and panics.
Common situations: Concurrent cleanup deleting the peer's original cwd, containers churning tmpfs mounts, race between packaging and tmp dir removal.
Related errors
- failed to get working directory
- error writing output
- error retrieving file info for file number %d
- Error creating block storage root dir [%s]: %s
- Could not build blockfilesInfo info from block files: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0a37d368846b0e19.
Report an issue: GitHub.