{"record":{"id":"f1213580c312de79","repo":"github/copilot-sdk","slug":"sruntimeexecutable-and-sruntimenode-must-be-prov","errorCode":null,"errorMessage":"%sRuntimeExecutable and %sRuntimeNode must be provided together","messagePattern":"(.+?)RuntimeExecutable and (.+?)RuntimeNode must be provided together","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/internal/embeddedcli/embeddedcli.go","lineNumber":419,"sourceCode":"\t\t\treturn fmt.Errorf(\"reading runtime asset %q: %w\", header.Name, err)\n\t\t}\n\t\tpath := filepath.Join(installDir, clean)\n\t\tif err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {\n\t\t\treturn fmt.Errorf(\"creating runtime asset directory: %w\", err)\n\t\t}\n\t\thash := sha256.Sum256(content)\n\t\tmode := os.FileMode(header.Mode & 0777)\n\t\tif err := installVerifiedFile(path, bytes.NewReader(content), hash[:], mode, \"runtime asset\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\truntimeAssetsInstalled = true\n\treturn nil\n}\n\nfunc validateRuntimePairConfig(wrapper io.Reader, wrapperHash []byte, node io.Reader, nodeHash []byte, prefix string) {\n\tif (wrapper == nil) != (node == nil) {\n\t\tpanic(prefix + \"RuntimeExecutable and \" + prefix + \"RuntimeNode must be provided together\")\n\t}\n\tif wrapper == nil {\n\t\treturn\n\t}\n\tif len(wrapperHash) != sha256.Size {\n\t\tpanic(fmt.Sprintf(\"%sRuntimeExecutableHash must be a SHA-256 hash (%d bytes), got %d bytes\", prefix, sha256.Size, len(wrapperHash)))\n\t}\n\tif len(nodeHash) != sha256.Size {\n\t\tpanic(fmt.Sprintf(\"%sRuntimeNodeHash must be a SHA-256 hash (%d bytes), got %d bytes\", prefix, sha256.Size, len(nodeHash)))\n\t}\n}\n\nfunc installRuntimePair(installDir string) (string, error) {\n\tnodePath := filepath.Join(installDir, \"runtime.node\")\n\tif err := installVerifiedFile(nodePath, config.RuntimeNode, config.RuntimeNodeHash, 0644, \"runtime.node\"); err != nil {\n\t\treturn \"\", err\n\t}\n\twrapperPath := filepath.Join(installDir, runtimeExecutableName())","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/internal/embeddedcli/embeddedcli.go#L401-L437","documentation":"validateRuntimePairConfig requires the platform runtime wrapper executable and the runtime node library to be configured together: one without the other is an invalid state because the installed runtime is only coherent as a pair. Setup panics when exactly one of (wrapper, node) is nil. The check runs for every configured platform prefix (e.g. \"LinuxMusl\") and for the default pair.","triggerScenarios":"Calling Setup with cfg.LinuxMuslRuntimeExecutable set but cfg.LinuxMuslRuntimeNode nil (or vice versa); partially populating a Config struct and forgetting the sibling field; build tags injecting only one of the two embedded assets.","commonSituations":"Cross-compiling for a platform where only one asset was embedded into the binary; hand-edited config code that set the executable but not the node library; conditional builds that strip one resource.","solutions":["Provide both fields for the platform: set cfg.LinuxMuslRuntimeNode (and its hash) whenever cfg.LinuxMuslRuntimeExecutable is set.","If the platform's runtime is intentionally absent, clear both fields so the pair is nil/nil and the validator returns early.","Check your build embedding (go:embed / ldflags injection) so both assets for each platform are compiled in."],"exampleFix":"// before\ncfg.LinuxMuslRuntimeExecutable = wrapperReader\ncfg.LinuxMuslRuntimeExecutableHash = wrapperHash\n// LinuxMuslRuntimeNode forgotten\n\n// after\ncfg.LinuxMuslRuntimeExecutable = wrapperReader\ncfg.LinuxMuslRuntimeExecutableHash = wrapperHash\ncfg.LinuxMuslRuntimeNode = nodeReader\ncfg.LinuxMuslRuntimeNodeHash = nodeHash","handlingStrategy":"validation","validationCode":"func pairComplete(exec, node io.Reader) bool { return (exec == nil) == (node == nil) }","typeGuard":"func hasRuntimePair(cfg Config) bool {\n    return (cfg.LinuxMuslRuntimeExecutable == nil) == (cfg.LinuxMuslRuntimeNode == nil)\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if s, ok := r.(string); ok && strings.Contains(s, \"must be provided together\") {\n            log.Fatalf(\"runtime pair misconfigured: %s\", s)\n        }\n        panic(r)\n    }\n}()","preventionTips":["Set both pair fields together in a single constructor/helper function for the platform.","Audit go:embed directives so every platform embeds both the executable and the node library.","Add a unit test that runs Setup with your production Config in CI."],"tags":["go","panic","config-validation","embedded-runtime"],"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-15T23:17:13.987Z"}