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

  1. Set Config.Cli to a non-nil io.Reader containing the CLI binary
  2. Check for typed-nil: ensure the concrete value behind the interface is non-nil
  3. Verify build tags/embedding so the CLI asset is actually available at Setup time
  4. 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

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


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)