{"record":{"id":"8d95c040e57b1d34","repo":"github/copilot-sdk","slug":"reading-runtime-assets-w","errorCode":null,"errorMessage":"reading runtime assets: %w","messagePattern":"reading runtime assets: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/internal/embeddedcli/embeddedcli.go","lineNumber":372,"sourceCode":"\treturn path, nil\n}\n\nfunc validateOptionalHash(reader io.Reader, hash []byte, name string) {\n\tif reader != nil && len(hash) != sha256.Size {\n\t\tpanic(fmt.Sprintf(\"%s must be a SHA-256 hash (%d bytes), got %d bytes\", name, sha256.Size, len(hash)))\n\t}\n}\n\nfunc installRuntimeAssets(installDir string) error {\n\tif config.RuntimeAssets == nil || runtimeAssetsInstalled {\n\t\treturn nil\n\t}\n\tarchiveBytes, err := io.ReadAll(config.RuntimeAssets)\n\tif closer, ok := config.RuntimeAssets.(io.Closer); ok {\n\t\tcloser.Close()\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reading runtime assets: %w\", err)\n\t}\n\tactual := sha256.Sum256(archiveBytes)\n\tif !bytes.Equal(actual[:], config.RuntimeAssetsHash) {\n\t\treturn fmt.Errorf(\"runtime assets hash mismatch\")\n\t}\n\tgzipReader, err := gzip.NewReader(bytes.NewReader(archiveBytes))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"opening runtime assets: %w\", err)\n\t}\n\tdefer gzipReader.Close()\n\ttarReader := tar.NewReader(gzipReader)\n\tfor {\n\t\theader, err := tarReader.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reading runtime assets: %w\", err)","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/internal/embeddedcli/embeddedcli.go#L354-L390","documentation":"installRuntimeAssets slurps the entire runtime archive from config.RuntimeAssets via io.ReadAll. Any read failure is wrapped as \"reading runtime assets\". This is the first integrity step before hash verification and extraction.","triggerScenarios":"io.ReadAll(config.RuntimeAssets) errors: the embedded asset reader is nil-backed/closed, a network/HTTP body reader was interrupted, or an fs.File/bytes source hit an I/O error.","commonSituations":"Embedding an asset via a flaky network fetch at startup; passing an already-closed reader as RuntimeAssets; interrupted download of runtime archives.","solutions":["Verify RuntimeAssets points to a valid, open reader (e.g. bytes.NewReader or embed.FS Open)","If sourced over the network, retry the download before install","Confirm the embedded runtime asset exists in the build (go:embed pattern matches)","Wrap the source in a buffered reader built from a complete local copy"],"exampleFix":"// before\ncfg.RuntimeAssets = closedReader // read failed\n// after\nf, err := assets.Open(\"runtime.tar.gz\")\nif err != nil { return err }\ndefer f.Close()\ncfg.RuntimeAssets = f","handlingStrategy":"try-catch","validationCode":"if cfg.RuntimeAssets == nil { return errors.New(\"RuntimeAssets reader not set\") }\nif c, ok := cfg.RuntimeAssets.(io.Closer); ok { /* ensure not already closed */ _ = c }","typeGuard":"func hasRuntimeAssets(cfg embeddedcli.Config) bool {\n    return cfg.RuntimeAssets != nil && cfg.RuntimeAssetsHash != nil\n}","tryCatchPattern":"err := embeddedcli.InstallRuntime(ctx, cfg, dir)\nif err != nil && strings.Contains(err.Error(), \"reading runtime assets\") {\n    return retryWithFreshReader(ctx) // rebuild the reader and retry once\n}","preventionTips":["Always pass a fresh, open reader for RuntimeAssets","Load assets fully into memory before install if sourced over the network","Confirm embedded assets exist at build time (go:embed errors) before shipping"],"tags":["io","assets","archive"],"backgroundTag":"file-read-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}