{"record":{"id":"c5d146ca11bd5ea6","repo":"github/copilot-sdk","slug":"cli-reader-is-required","errorCode":null,"errorMessage":"Cli reader is required","messagePattern":"Cli reader is required","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/internal/embeddedcli/embeddedcli.go","lineNumber":67,"sourceCode":"\t// automatically when the application runs on a musl-based Linux system.\n\tLinuxMuslCli                   io.Reader\n\tLinuxMuslCliHash               []byte\n\tLinuxMuslRuntimeLib            io.Reader\n\tLinuxMuslRuntimeLibHash        []byte\n\tLinuxMuslRuntimeExecutable     io.Reader\n\tLinuxMuslRuntimeExecutableHash []byte\n\tLinuxMuslRuntimeNode           io.Reader\n\tLinuxMuslRuntimeNodeHash       []byte\n\tLinuxMuslRuntimeAssets         io.Reader\n\tLinuxMuslRuntimeAssetsHash     []byte\n\n\tDir     string\n\tVersion string\n}\n\nfunc Setup(cfg Config) {\n\tif cfg.Cli == nil {\n\t\tpanic(\"Cli reader is required\")\n\t}\n\tif len(cfg.CliHash) != sha256.Size {\n\t\tpanic(fmt.Sprintf(\"CliHash must be a SHA-256 hash (%d bytes), got %d bytes\", sha256.Size, len(cfg.CliHash)))\n\t}\n\tif cfg.LinuxMuslCli != nil && len(cfg.LinuxMuslCliHash) != sha256.Size {\n\t\tpanic(fmt.Sprintf(\"LinuxMuslCliHash must be a SHA-256 hash (%d bytes), got %d bytes\", sha256.Size, len(cfg.LinuxMuslCliHash)))\n\t}\n\tif cfg.LinuxMuslRuntimeLib != nil && len(cfg.LinuxMuslRuntimeLibHash) != sha256.Size {\n\t\tpanic(fmt.Sprintf(\"LinuxMuslRuntimeLibHash must be a SHA-256 hash (%d bytes), got %d bytes\", sha256.Size, len(cfg.LinuxMuslRuntimeLibHash)))\n\t}\n\tvalidateRuntimePairConfig(cfg.RuntimeExecutable, cfg.RuntimeExecutableHash, cfg.RuntimeNode, cfg.RuntimeNodeHash, \"\")\n\tvalidateRuntimePairConfig(cfg.LinuxMuslRuntimeExecutable, cfg.LinuxMuslRuntimeExecutableHash, cfg.LinuxMuslRuntimeNode, cfg.LinuxMuslRuntimeNodeHash, \"LinuxMusl\")\n\tvalidateOptionalHash(cfg.RuntimeAssets, cfg.RuntimeAssetsHash, \"RuntimeAssetsHash\")\n\tvalidateOptionalHash(cfg.LinuxMuslRuntimeAssets, cfg.LinuxMuslRuntimeAssetsHash, \"LinuxMuslRuntimeAssetsHash\")\n\tsetupMu.Lock()\n\tdefer setupMu.Unlock()\n\tif setupDone {\n\t\tpanic(\"Setup must only be called once\")","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/internal/embeddedcli/embeddedcli.go#L49-L85","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nembeddedcli.Setup(embeddedcli.Config{Version: \"1.2.3\"})\n// after\nembeddedcli.Setup(embeddedcli.Config{Cli: bytes.NewReader(cliBin), CliHash: cliHash, Version: \"1.2.3\"})","handlingStrategy":"validation","validationCode":"if cfg.Cli == nil {\n\treturn errors.New(\"embeddedcli.Config.Cli must be a non-nil io.Reader\")\n}","typeGuard":"func cliReaderSet(r io.Reader) bool {\n\tif r == nil { return false }\n\tv := reflect.ValueOf(r)\n\treturn v.Kind() != reflect.Ptr || !v.IsNil()\n}","tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tlog.Fatalf(\"embeddedcli.Setup failed: %v\", r)\n\t}\n}()","preventionTips":["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"],"tags":["go","config","panic","embedded"],"backgroundTag":"missing-required-config-field","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}