{"record":{"id":"45968288cddb9696","repo":"istio/istio","slug":"config-writer-has-not-been-primed-459682","errorCode":null,"errorMessage":"config writer has not been primed","messagePattern":"config writer has not been primed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"istioctl/pkg/writer/envoy/configdump/endpoint.go","lineNumber":107,"sourceCode":"\t\t\tresult = append(result, addr.GetPath())\n\t\t\tcontinue\n\t\t}\n\t\tif internal := addr.GetEnvoyInternalAddress(); internal != nil {\n\t\t\tswitch an := internal.GetAddressNameSpecifier().(type) {\n\t\t\tcase *core.EnvoyInternalAddress_ServerListenerName:\n\t\t\t\tresult = append(result, fmt.Sprintf(\"envoy://%s/%s\", an.ServerListenerName, internal.EndpointId))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tresult = append(result, \"unknown\")\n\t}\n\n\treturn result\n}\n\nfunc (c *ConfigWriter) PrintEndpoints(filter EndpointFilter, outputFormat string) error {\n\tif c.configDump == nil {\n\t\treturn fmt.Errorf(\"config writer has not been primed\")\n\t}\n\tdump, err := c.retrieveSortedEndpointsSlice(filter)\n\tif err != nil {\n\t\treturn err\n\t}\n\tmarshaller := make(proto.MessageSlice, 0, len(dump))\n\tfor _, eds := range dump {\n\t\tmarshaller = append(marshaller, eds)\n\t}\n\tout, err := json.MarshalIndent(marshaller, \"\", \"    \")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif outputFormat == \"yaml\" {\n\t\tif out, err = yaml.JSONToYAML(out); err != nil {\n\t\t\treturn err\n\t\t}\n\t}","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/istio/istio/blob/8dc789c5cf17517c64e3c36cb3288230f149dfae/istioctl/pkg/writer/envoy/configdump/endpoint.go#L89-L125","documentation":"Guard in ConfigWriter.PrintEndpoints (istioctl/pkg/writer/envoy/configdump/endpoint.go:107): the Envoy endpoints (clusters/load-assignment) view cannot be printed because the writer was never primed. Like every Print* method, PrintEndpoints dereferences c.configDump (via retrieveSortedEndpointsSlice) which is only set by a successful Prime(configDumpBytes) call.","triggerScenarios":"Calling PrintEndpoints / PrintEndpointsSummary on a ConfigWriter whose Prime was skipped or whose Prime errored ('error unmarshalling config dump response from Envoy') with the error swallowed. This is the path behind `istioctl proxy-config endpoint <pod>`.","commonSituations":"Programmatic reuse of the writer where a fetch failure is ignored; integrating configdump printing into another tool that constructs the struct directly.","solutions":["Fetch the pod's /config_dump and Prime the writer, checking the error, before printing endpoints","Centralize prime-then-print in one helper so no Print* can be reached un-primed","Treat a Prime failure as fatal for that pod instead of continuing with an empty writer"],"exampleFix":"// before\ncw := configdump.NewConfigWriter(os.Stdout)\ncw.PrintEndpoints(configdump.EndpointFilter{}, \"json\") // not primed\n\n// after\nif err := cw.Prime(dump); err != nil {\n    return err\n}\nreturn cw.PrintEndpoints(configdump.EndpointFilter{}, \"json\")","handlingStrategy":"validation","validationCode":"if len(dumpBytes) == 0 {\n    return errors.New(\"no config dump fetched; cannot print endpoints\")\n}\nif err := cw.Prime(dumpBytes); err != nil {\n    return fmt.Errorf(\"prime: %w\", err)\n}\nreturn cw.PrintEndpoints(filter, \"json\")","typeGuard":null,"tryCatchPattern":"if err := cw.PrintEndpoints(filter, output); err != nil {\n    if strings.Contains(err.Error(), \"has not been primed\") {\n        return fmt.Errorf(\"bug: PrintEndpoints before Prime: %w\", err)\n    }\n    return err\n}","preventionTips":["Fetch -> Prime -> print as one unit of work","Fail the whole command when the dump fetch fails rather than printing","Lint/test for un-primed writer usage in wrappers"],"tags":["istio","istioctl","configdump","endpoints","api-misuse","go"],"backgroundTag":null,"analyzedSha":"8dc789c5cf17517c64e3c36cb3288230f149dfae","analyzedAt":"2026-08-15T15:16:55.434Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}