github/copilot-sdk · error
Cli reader is required
Error message
Cli reader is required
What it means
embeddedcli.Setup validates its Config before installing the embedded CLI. If cfg.Cli is nil — i.e. no reader supplying the CLI binary was provided — Setup panics immediately. The CLI reader is the one mandatory input; everything else in Config is optional or validated separately.
Solutions
- Set Config.Cli to a non-nil io.Reader containing the CLI binary
- Check for typed-nil: ensure the concrete value behind the interface is non-nil
- Verify build tags/embedding so the CLI asset is actually available at Setup time
- Ensure Setup is only called once (second calls panic elsewhere) with a fully populated Config
Example fix
// before
embeddedcli.Setup(embeddedcli.Config{Version: "1.2.3"})
// after
embeddedcli.Setup(embeddedcli.Config{Cli: bytes.NewReader(cliBin), CliHash: cliHash, Version: "1.2.3"}) Defensive patterns
Strategy: validation
Validate before calling
if cfg.Cli == nil {
return errors.New("embeddedcli.Config.Cli must be a non-nil io.Reader")
} Type guard
func cliReaderSet(r io.Reader) bool {
if r == nil { return false }
v := reflect.ValueOf(r)
return v.Kind() != reflect.Ptr || !v.IsNil()
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("embeddedcli.Setup failed: %v", r)
}
}() Prevention
- Always populate Config.Cli in a single shared constructor
- Beware typed-nil pointers assigned to interface fields
- Centralize embedded asset wiring so build tags cannot silently nil the reader
- Call Setup exactly once from package init or main
When it happens
Trigger: Calling embeddedcli.Setup(Config{...}) without setting the Cli field, or setting it to a nil io.Reader/typed-nil (e.g. a nil *bytes.Reader stored in an interface).
Common situations: Constructing Config programmatically and skipping Cli, wiring embedded assets conditionally so the field ends up nil in some builds, or passing a typed-nil pointer that satisfies the interface check only via nil interface comparison.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- CliHash must be a SHA-256 hash
- in-process runtime unavailable: build with the bundled…
- failed to set model: AutoTier and ResetAutoTier are…
- GitHubToken and GitHubTokenProvider cannot be used together
- CreateSessionFSProvider is required in session config when…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/c5d146ca11bd5ea6.
Report an issue: GitHub.
Appendix: source
Thrown at go/internal/embeddedcli/embeddedcli.go:67
// automatically when the application runs on a musl-based Linux system.
LinuxMuslCli io.Reader
LinuxMuslCliHash []byte
LinuxMuslRuntimeLib io.Reader
LinuxMuslRuntimeLibHash []byte
LinuxMuslRuntimeExecutable io.Reader
LinuxMuslRuntimeExecutableHash []byte
LinuxMuslRuntimeNode io.Reader
LinuxMuslRuntimeNodeHash []byte
LinuxMuslRuntimeAssets io.Reader
LinuxMuslRuntimeAssetsHash []byte
Dir string
Version string
}
func Setup(cfg Config) {
if cfg.Cli == nil {
panic("Cli reader is required")
}
if len(cfg.CliHash) != sha256.Size {
panic(fmt.Sprintf("CliHash must be a SHA-256 hash (%d bytes), got %d bytes", sha256.Size, len(cfg.CliHash)))
}
if cfg.LinuxMuslCli != nil && len(cfg.LinuxMuslCliHash) != sha256.Size {
panic(fmt.Sprintf("LinuxMuslCliHash must be a SHA-256 hash (%d bytes), got %d bytes", sha256.Size, len(cfg.LinuxMuslCliHash)))
}
if cfg.LinuxMuslRuntimeLib != nil && len(cfg.LinuxMuslRuntimeLibHash) != sha256.Size {
panic(fmt.Sprintf("LinuxMuslRuntimeLibHash must be a SHA-256 hash (%d bytes), got %d bytes", sha256.Size, len(cfg.LinuxMuslRuntimeLibHash)))
}
validateRuntimePairConfig(cfg.RuntimeExecutable, cfg.RuntimeExecutableHash, cfg.RuntimeNode, cfg.RuntimeNodeHash, "")
validateRuntimePairConfig(cfg.LinuxMuslRuntimeExecutable, cfg.LinuxMuslRuntimeExecutableHash, cfg.LinuxMuslRuntimeNode, cfg.LinuxMuslRuntimeNodeHash, "LinuxMusl")
validateOptionalHash(cfg.RuntimeAssets, cfg.RuntimeAssetsHash, "RuntimeAssetsHash")
validateOptionalHash(cfg.LinuxMuslRuntimeAssets, cfg.LinuxMuslRuntimeAssetsHash, "LinuxMuslRuntimeAssetsHash")
setupMu.Lock()
defer setupMu.Unlock()
if setupDone {
panic("Setup must only be called once")View on GitHub (pinned to cd8cf15dc3)